module Unix:sig
..end
Unix 系统的接口。
要使用此模块的带标签版本,请在您的实现中添加 module Unix
=
UnixLabels
。
注意:此模块的所有函数(除了 Unix.error_message
和 Unix.handle_unix_error
)在底层系统调用发出错误信号时,都可能引发 Unix.Unix_error
异常。
type
error =
| |
E2BIG |
(* | 参数列表过长 | *) |
| |
EACCES |
(* | 权限被拒绝 | *) |
| |
EAGAIN |
(* | 资源暂时不可用;请重试 | *) |
| |
EBADF |
(* | 错误的文件描述符 | *) |
| |
EBUSY |
(* | 资源不可用 | *) |
| |
ECHILD |
(* | 没有子进程 | *) |
| |
EDEADLK |
(* | 将发生资源死锁 | *) |
| |
EDOM |
(* | 数学函数等的域错误 | *) |
| |
EEXIST |
(* | 文件已存在 | *) |
| |
EFAULT |
(* | 错误的地址 | *) |
| |
EFBIG |
(* | 文件过大 | *) |
| |
EINTR |
(* | 函数被信号中断 | *) |
| |
EINVAL |
(* | 无效的参数 | *) |
| |
EIO |
(* | 硬件 I/O 错误 | *) |
| |
EISDIR |
(* | 是目录 | *) |
| |
EMFILE |
(* | 进程打开的文件过多 | *) |
| |
EMLINK |
(* | 链接过多 | *) |
| |
ENAMETOOLONG |
(* | 文件名过长 | *) |
| |
ENFILE |
(* | 系统中打开的文件过多 | *) |
| |
ENODEV |
(* | 没有这样的设备 | *) |
| |
ENOENT |
(* | 没有这样的文件或目录 | *) |
| |
ENOEXEC |
(* | 不是可执行文件 | *) |
| |
ENOLCK |
(* | 没有可用的锁 | *) |
| |
ENOMEM |
(* | 内存不足 | *) |
| |
ENOSPC |
(* | 设备上没有剩余空间 | *) |
| |
ENOSYS |
(* | 不支持该函数 | *) |
| |
ENOTDIR |
(* | 不是目录 | *) |
| |
ENOTEMPTY |
(* | 目录不为空 | *) |
| |
ENOTTY |
(* | 不合适的 I/O 控制操作 | *) |
| |
ENXIO |
(* | 没有这样的设备或地址 | *) |
| |
EPERM |
(* | 操作不被允许 | *) |
| |
EPIPE |
(* | 管道破裂 | *) |
| |
ERANGE |
(* | 结果过大 | *) |
| |
EROFS |
(* | 只读文件系统 | *) |
| |
ESPIPE |
(* | 无效的查找,例如在管道上 | *) |
| |
ESRCH |
(* | 没有这样的进程 | *) |
| |
EXDEV |
(* | 无效的链接 | *) |
| |
EWOULDBLOCK |
(* | 操作将阻塞 | *) |
| |
EINPROGRESS |
(* | 操作正在进行中 | *) |
| |
EALREADY |
(* | 操作已经在进行中 | *) |
| |
ENOTSOCK |
(* | 在非套接字上进行套接字操作 | *) |
| |
EDESTADDRREQ |
(* | 需要目标地址 | *) |
| |
EMSGSIZE |
(* | 消息过长 | *) |
| |
EPROTOTYPE |
(* | 套接字的协议类型错误 | *) |
| |
ENOPROTOOPT |
(* | 协议不可用 | *) |
| |
EPROTONOSUPPORT |
(* | 不支持该协议 | *) |
| |
ESOCKTNOSUPPORT |
(* | 不支持套接字类型 | *) |
| |
EOPNOTSUPP |
(* | 套接字不支持该操作 | *) |
| |
EPFNOSUPPORT |
(* | 不支持协议族 | *) |
| |
EAFNOSUPPORT |
(* | 协议族不支持地址族 | *) |
| |
EADDRINUSE |
(* | 地址已被使用 | *) |
| |
EADDRNOTAVAIL |
(* | 无法分配请求的地址 | *) |
| |
ENETDOWN |
(* | 网络已断开 | *) |
| |
ENETUNREACH |
(* | 网络不可达 | *) |
| |
ENETRESET |
(* | 网络在重置时断开了连接 | *) |
| |
ECONNABORTED |
(* | 软件导致连接中止 | *) |
| |
ECONNRESET |
(* | 连接被对等方重置 | *) |
| |
ENOBUFS |
(* | 没有可用的缓冲区空间 | *) |
| |
EISCONN |
(* | 套接字已连接 | *) |
| |
ENOTCONN |
(* | 套接字未连接 | *) |
| |
ESHUTDOWN |
(* | 套接字关闭后无法发送 | *) |
| |
ETOOMANYREFS |
(* | 引用过多:无法拼接 | *) |
| |
ETIMEDOUT |
(* | 连接超时 | *) |
| |
ECONNREFUSED |
(* | 连接被拒绝 | *) |
| |
EHOSTDOWN |
(* | 主机已关闭 | *) |
| |
EHOSTUNREACH |
(* | 无法访问主机 | *) |
| |
ELOOP |
(* | 符号链接级别过多 | *) |
| |
EOVERFLOW |
(* | 文件大小或位置无法表示 | *) |
| |
EUNKNOWNERR of |
(* | 未知错误 | *) |
错误代码的类型。POSIX 标准中定义的错误以及来自 UNIX98 和 BSD 的其他错误。所有其他错误都映射到 EUNKNOWNERR。
exception Unix_error of error * string * string
当遇到错误时,以下系统调用会引发此异常。第一个组件是错误代码;第二个组件是函数名称;第三个组件是函数的字符串参数(如果存在),否则为空字符串。
UnixLabels.Unix_error
和 Unix.Unix_error
是相同的,捕获其中一个将捕获另一个。
val error_message : error -> string
返回描述给定错误代码的字符串。
val handle_unix_error : ('a -> 'b) -> 'a -> 'b
handle_unix_error f x
将 f
应用于 x
并返回结果。如果引发了 Unix.Unix_error
异常,它将打印一条描述错误的消息并以代码 2 退出。
val environment : unit -> string array
返回进程环境,作为一个字符串数组,格式为“变量=值”。如果进程具有特殊权限,则返回的数组为空。
val unsafe_environment : unit -> string array
返回进程环境,作为一个字符串数组,格式为“变量=值”。与 Unix.environment
不同,即使进程具有特殊权限,此函数也会返回一个填充的数组。有关更多详细信息,请参阅 Unix.unsafe_getenv
的文档。
val getenv : string -> string
返回与进程环境中变量关联的值,除非进程具有特殊权限。
Not_found
,如果变量未绑定或进程具有特殊权限。此函数与 Sys.getenv
相同。val unsafe_getenv : string -> string
返回与进程环境中变量关联的值。
与 Unix.getenv
不同,即使进程具有特殊权限,此函数也会返回值。它被认为是不安全的,因为 setuid 或 setgid 程序的程序员必须小心避免在可执行文件的搜索路径、临时文件或日志的位置等中使用恶意构建的环境变量。
Not_found
,如果变量未绑定。val putenv : string -> string -> unit
putenv name value
设置与进程环境中变量关联的值。name
是环境变量的名称,value
是其新的关联值。
type
process_status =
| |
WEXITED of |
(* | 进程通过 | *) |
| |
WSIGNALED of |
(* | 进程被信号杀死;参数是信号编号。 | *) |
| |
WSTOPPED of |
(* | 进程被信号停止;参数是信号编号。 | *) |
进程的终止状态。有关标准信号编号的定义,请参阅模块 Sys
。请注意,它们不是操作系统使用的编号。
在 Windows 上:仅使用 WEXITED
(因为没有进程间信号),但使用特定的返回代码来指示特殊的终止原因。请在 Windows 文档中查找 NTSTATUS
值以解码此类错误返回代码。特别是,STATUS_ACCESS_VIOLATION
错误代码是 32 位 0xC0000005
:由于 Int32.of_int 0xC0000005
是 -1073741819
,WEXITED -1073741819
是 WSIGNALED Sys.sigsegv
的 Windows 等效项。
type
wait_flag =
| |
WNOHANG |
(* | 如果还没有子进程死亡,则不要阻塞,而是立即返回 pid 等于 0。 | *) |
| |
WUNTRACED |
(* | 也报告接收停止信号的子进程。 | *) |
Unix.waitpid
的标志。
val execv : string -> string array -> 'a
execv prog args
执行文件 prog
中的程序,使用参数 args
和当前进程环境。请注意,第一个参数 args.(0)
按照惯例是正在执行的程序的文件名,就像 Sys.argv.(0)
一样。这些 execv*
函数永远不会返回:成功时,当前程序将被新程序替换。
在 Windows 上:CRT 只是生成一个新进程并退出当前进程。如果例如另一个进程正在等待当前进程,则这将产生不希望的结果。建议改为使用 Unix.create_process
或 open_process_*
函数之一。
Unix_error
val execve : string -> string array -> string array -> 'a
与 Unix.execv
相同,只是第三个参数为正在执行的程序提供环境。
val execvp : string -> string array -> 'a
与 Unix.execv
相同,只是在路径中搜索程序。
val execvpe : string -> string array -> string array -> 'a
与 Unix.execve
相同,只是在路径中搜索程序。
val fork : unit -> int
创建一个新的进程。对于子进程,返回的整数为 0;对于父进程,返回子进程的进程 ID (pid)。如果 OCaml 进程是多核的(任何域都已被生成),则会失败。此外,如果 Thread 模块中的任何线程已被生成,则子进程可能处于损坏状态。
Invalid_argument
异常。请使用 Unix.create_process
或线程代替。Failure
异常。val wait : unit -> int * process_status
等待其中一个子进程死亡,并返回其进程 ID 和终止状态。
Invalid_argument
异常。请使用 Unix.waitpid
代替。val waitpid : wait_flag list -> int -> int * process_status
与 Unix.wait
相同,但等待进程 ID 为给定值的子进程。进程 ID 为 -1
表示等待任何子进程。进程 ID 为 0
表示等待与当前进程位于同一进程组中的任何子进程。负的进程 ID 参数表示进程组。选项列表指示 waitpid
是否应该立即返回而不等待,以及是否应该报告已停止的子进程。
在 Windows 上:只能等待给定的 PID,而不是任何子进程。
val system : string -> process_status
执行给定的命令,等待其终止,并返回其终止状态。该字符串由 shell /bin/sh
(或 Windows 上的命令解释器 cmd.exe
)解释,因此可以包含重定向、引号、变量等。为了正确引用文件名或命令参数中出现的空格和 shell 特殊字符,建议使用 Filename.quote_command
。结果 WEXITED 127
表示 shell 无法执行。
val _exit : int -> 'a
立即终止调用进程,并将给定的状态代码返回给操作系统:通常为 0 表示没有错误,一个小正整数表示失败。与 exit
不同,Unix._exit
不会执行任何最终化操作:使用 at_exit
注册的函数不会被调用,输入/输出通道不会被刷新,C 运行时系统也不会被最终化。
通常在 Unix.fork
操作之后使用 Unix._exit
,当子进程遇到致命错误并必须退出时。在这种情况下,最好不要在子进程中执行任何最终化操作,因为这些操作可能会干扰父进程执行的类似操作。例如,子进程不应刷新输出通道,因为父进程以后可能会再次刷新它们,从而导致输出重复。
val getpid : unit -> int
返回进程的进程 ID。
val getppid : unit -> int
返回父进程的进程 ID。
Invalid_argument
异常(因为它是没有意义的)val nice : int -> int
更改进程优先级。整数参数将添加到“nice”值中。(“nice”值越高,优先级越低。)返回新的 nice 值。
Invalid_argument
异常type
file_descr
文件描述符的抽象类型。
val stdin : file_descr
标准输入的文件描述符。
val stdout : file_descr
标准输出的文件描述符。
val stderr : file_descr
标准错误的文件描述符。
type
open_flag =
| |
O_RDONLY |
(* | 以只读方式打开 | *) |
| |
O_WRONLY |
(* | 以只写方式打开 | *) |
| |
O_RDWR |
(* | 以读写方式打开 | *) |
| |
O_NONBLOCK |
(* | 以非阻塞模式打开 | *) |
| |
O_APPEND |
(* | 以追加方式打开 | *) |
| |
O_CREAT |
(* | 如果不存在则创建 | *) |
| |
O_TRUNC |
(* | 如果存在则截断为 0 长度 | *) |
| |
O_EXCL |
(* | 如果存在则失败 | *) |
| |
O_NOCTTY |
(* | 不要将此设备设为控制终端 | *) |
| |
O_DSYNC |
(* | 写入完成作为“同步 I/O 数据完整性完成” | *) |
| |
O_SYNC |
(* | 写入完成作为“同步 I/O 文件完整性完成” | *) |
| |
O_RSYNC |
(* | 读取完成作为写入(取决于 O_SYNC/O_DSYNC) | *) |
| |
O_SHARE_DELETE |
(* | 仅限 Windows:允许在文件仍处于打开状态时将其删除 | *) |
| |
O_CLOEXEC |
(* | 在 | *) |
| |
O_KEEPEXEC |
(* | 清除 close-on-exec 标志。这目前是默认设置。 | *) |
传递给 Unix.openfile
的标志。
typefile_perm =
int
文件访问权限的类型,例如 0o640
表示用户可读写,组可读,其他用户不可访问
val openfile : string -> open_flag list -> file_perm -> file_descr
使用给定的标志打开指定名称的文件。第三个参数是在创建文件时赋予文件的权限(请参阅 Unix.umask
)。返回指定名称文件的描述符。
val close : file_descr -> unit
关闭文件描述符。
val fsync : file_descr -> unit
将文件缓冲区刷新到磁盘。
val read : file_descr -> bytes -> int -> int -> int
read fd buf pos len
从描述符 fd
读取 len
个字节,将它们存储在字节序列 buf
中,从 buf
中的 pos
位置开始。返回实际读取的字节数。
val read_bigarray : file_descr ->
('a, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
Bigarray.Array1.t -> int -> int -> int
与 Unix.read
相同,但将数据读取到一个大数组中。
val write : file_descr -> bytes -> int -> int -> int
write fd buf pos len
将 len
个字节写入描述符 fd
,从字节序列 buf
中获取,从 buff
中的 pos
位置开始。返回实际写入的字节数。write
重复写入操作,直到所有字节都已写入或发生错误。
val write_bigarray : file_descr ->
('a, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
Bigarray.Array1.t -> int -> int -> int
与 Unix.write
相同,但从大数组中获取数据。
val single_write : file_descr -> bytes -> int -> int -> int
与 Unix.write
相同,但只尝试写入一次。因此,如果发生错误,single_write
保证没有数据被写入。
val write_substring : file_descr -> string -> int -> int -> int
与 Unix.write
相同,但从字符串而不是字节序列中获取数据。
val single_write_substring : file_descr -> string -> int -> int -> int
与 Unix.single_write
相同,但从字符串而不是字节序列中获取数据。
val single_write_bigarray : file_descr ->
('a, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
Bigarray.Array1.t -> int -> int -> int
与 Unix.single_write
相同,但从大数组中获取数据。
val in_channel_of_descr : file_descr -> in_channel
创建一个从给定描述符读取的输入通道。该通道最初处于二进制模式;如果需要文本模式,请使用 set_binary_mode_in ic false
。文本模式仅在描述符引用文件或管道时受支持,但不支持引用套接字时。
在 Windows 上:set_binary_mode_in
在使用此函数创建的通道上始终失败。
请注意,输入通道是缓冲的,因此可能已从描述符中读取了比使用通道函数访问的更多字符。通道还保留文件当前位置的副本。
使用 close_in ic
关闭由 in_channel_of_descr fd
返回的通道 ic
也会关闭底层描述符 fd
。同时关闭通道 ic
和描述符 fd
是错误的。
如果在同一描述符上创建了多个通道,则必须关闭其中一个通道,而不能关闭其他通道。例如,考虑一个连接到套接字的描述符 s
和两个通道 ic = in_channel_of_descr s
和 oc = out_channel_of_descr s
。建议的关闭协议是执行 close_out oc
,它将缓冲的输出刷新到套接字,然后关闭套接字。ic
通道不得关闭,并最终会被 GC 回收。
val out_channel_of_descr : file_descr -> out_channel
创建一个写入给定描述符的输出通道。该通道最初处于二进制模式;如果需要文本模式,请使用 set_binary_mode_out oc false
。文本模式仅在描述符引用文件或管道时受支持,但不支持引用套接字时。
在 Windows 上:set_binary_mode_out
在使用此函数创建的通道上始终失败。
请注意,输出通道是缓冲的,因此您可能需要调用 flush
以确保所有数据都已发送到描述符。通道还保留文件当前位置的副本。
使用 close_out oc
关闭由 out_channel_of_descr fd
返回的通道 oc
也会关闭底层描述符 fd
。同时关闭通道 ic
和描述符 fd
是错误的。
有关在同一描述符上创建多个通道时的关闭协议,请参阅 Unix.in_channel_of_descr
。
val descr_of_in_channel : in_channel -> file_descr
返回对应于输入通道的描述符。
val descr_of_out_channel : out_channel -> file_descr
返回对应于输出通道的描述符。
type
seek_command =
| |
SEEK_SET |
(* | 指示相对于文件开头的职位 | *) |
| |
SEEK_CUR |
(* | 指示相对于当前位置的职位 | *) |
| |
SEEK_END |
(* | 指示相对于文件末尾的职位 | *) |
用于 Unix.lseek
的定位模式。
val lseek : file_descr -> int -> seek_command -> int
设置文件描述符的当前位置,并返回结果偏移量(从文件开头算起)。
val truncate : string -> int -> unit
将指定名称的文件截断为给定大小。
val ftruncate : file_descr -> int -> unit
将对应于给定描述符的文件截断为给定大小。
type
file_kind =
| |
S_REG |
(* | 普通文件 | *) |
| |
S_DIR |
(* | 目录 | *) |
| |
S_CHR |
(* | 字符设备 | *) |
| |
S_BLK |
(* | 块设备 | *) |
| |
S_LNK |
(* | 符号链接 | *) |
| |
S_FIFO |
(* | 命名管道 | *) |
| |
S_SOCK |
(* | 套接字 | *) |
type
stats = {
|
st_dev : |
(* | 设备号 | *) |
|
st_ino : |
(* | 索引节点号 | *) |
|
st_kind : |
(* | 文件的种类 | *) |
|
st_perm : |
(* | 访问权限 | *) |
|
st_nlink : |
(* | 链接数 | *) |
|
st_uid : |
(* | 所有者的用户 ID | *) |
|
st_gid : |
(* | 文件所属组的组 ID | *) |
|
st_rdev : |
(* | 设备 ID(如果是特殊文件) | *) |
|
st_size : |
(* | 大小(以字节为单位) | *) |
|
st_atime : |
(* | 上次访问时间 | *) |
|
st_mtime : |
(* | 上次修改时间 | *) |
|
st_ctime : |
(* | 上次状态更改时间 | *) |
}
Unix.stat
调用返回的信息。
val stat : string -> stats
返回指定文件的相关信息。
val lstat : string -> stats
与 Unix.stat
相同,但如果文件是符号链接,则返回链接本身的信息。
val fstat : file_descr -> stats
返回与给定描述符关联的文件的信息。
val isatty : file_descr -> bool
如果给定的文件描述符指的是终端或控制台窗口,则返回 true
,否则返回 false
。
module LargeFile:sig
..end
大型文件的文件操作。
val map_file : file_descr ->
?pos:int64 ->
('a, 'b) Bigarray.kind ->
'c Bigarray.layout ->
bool -> int array -> ('a, 'b, 'c) Bigarray.Genarray.t
将文件内存映射为 Bigarray。 map_file fd kind layout shared dims
返回一个类型为 kind
、布局为 layout
且维度如 dims
中指定的 Bigarray。此 Bigarray 中包含的数据是文件描述符 fd
所引用的文件的内容(例如,之前使用 Unix.openfile
打开)。可选的 pos
参数是正在映射的数据在文件中的字节偏移量;默认为 0(从文件开头映射)。
如果 shared
为 true
,则对数组执行的所有修改都会反映在文件中。这要求 fd
以写权限打开。如果 shared
为 false
,则对数组执行的修改仅在内存中进行,使用修改页面的写时复制;基础文件不受影响。
Unix.map_file
比将整个文件读入 Bigarray、修改该 Bigarray 然后将其写回要高效得多。
要自动将 Bigarray 的维度调整为文件的实际大小,可以将主维度(即,对于具有 C 布局的数组,为第一个维度,对于具有 Fortran 布局的数组,为最后一个维度)指定为 -1
。然后,Unix.map_file
根据文件的大小确定主维度。文件必须包含由非主维度确定的整数个子数组,否则会引发 Failure
。
如果给出了 Bigarray 的所有维度,则将文件大小与 Bigarray 的大小进行匹配。如果文件大于 Bigarray,则仅将文件的前一部分映射到 Bigarray。如果文件小于 Bigarray,则文件会自动增长到 Bigarray 的大小。这要求对 fd
具有写权限。
对数组的访问会进行边界检查,但边界由对 map_file
的初始调用确定。因此,您应该确保在访问映射文件时没有其他进程修改它,否则可能会引发 SIGBUS 信号。例如,如果文件缩小,就会发生这种情况。
在参数验证失败的情况下,可能会引发 Invalid_argument
或 Failure
。
val unlink : string -> unit
删除指定的文件。
如果指定的文件是目录,则引发
EPERM
EISDIR
EACCESS
val rename : string -> string -> unit
rename src dst
将文件名称从 src
更改为 dst
,如果需要,将其在目录之间移动。如果 dst
已经存在,则其内容将被 src
的内容替换。根据操作系统,dst
的元数据(权限、所有者等)可以保留或被 src
的元数据替换。
val link : ?follow:bool -> string -> string -> unit
link ?follow src dst
创建一个名为 dst
的硬链接到名为 src
的文件。
~follow:_
但 linkat 不可使用,则在 Unix 上返回 ENOSYS
。~follow:false
,则在 Windows 上返回 ENOSYS
。follow
:指示是否遵循 src
符号链接或将创建到 src
本身的硬链接。在 Unix 系统上,这是使用 linkat(2)
函数完成的。如果未提供 ?follow
,则使用 link(2)
函数,其行为取决于操作系统,但可用性更广。val realpath : string -> string
realpath p
是 p
的绝对路径名,通过解析所有额外的 /
字符、相对路径段和符号链接获得。
type
access_permission =
| |
R_OK |
(* | 读取权限 | *) |
| |
W_OK |
(* | 写入权限 | *) |
| |
X_OK |
(* | 执行权限 | *) |
| |
F_OK |
(* | 文件已存在 | *) |
Unix.access
调用的标志。
val chmod : string -> file_perm -> unit
更改指定文件的权限。
val fchmod : file_descr -> file_perm -> unit
更改已打开文件的权限。
Invalid_argument
异常val chown : string -> int -> int -> unit
更改指定文件的所属用户 UID 和所属组 GID。
Invalid_argument
异常val fchown : file_descr -> int -> int -> unit
更改已打开文件的所属用户 UID 和所属组 GID。
Invalid_argument
异常val umask : file_perm -> file_perm
设置进程的文件模式创建掩码,并返回之前的掩码。
Invalid_argument
异常val access : string -> access_permission list -> unit
检查进程是否对指定文件具有给定的权限。
在 Windows 上:无法测试执行权限 X_OK
,仅测试读取权限。
Unix_error
,否则。val dup : ?cloexec:bool -> file_descr -> file_descr
返回一个新的文件描述符,该描述符引用与给定描述符相同的文件。有关可选参数 cloexec
的文档,请参阅 Unix.set_close_on_exec
。
val dup2 : ?cloexec:bool -> file_descr -> file_descr -> unit
dup2 src dst
将 src
复制到 dst
,如果 dst
已经打开,则将其关闭。有关可选参数 cloexec
的文档,请参阅 Unix.set_close_on_exec
。
val set_nonblock : file_descr -> unit
在给定的描述符上设置“非阻塞”标志。当设置了非阻塞标志时,在暂时没有可用数据的描述符上读取会引发 EAGAIN
或 EWOULDBLOCK
错误,而不是阻塞;在暂时没有写入空间的描述符上写入也会引发 EAGAIN
或 EWOULDBLOCK
。
val clear_nonblock : file_descr -> unit
清除给定描述符上的“非阻塞”标志。请参阅 Unix.set_nonblock
。
val set_close_on_exec : file_descr -> unit
在给定的描述符上设置“关闭-执行”标志。当当前进程使用 exec
、create_process
和 open_process
函数之一启动另一个程序时,具有关闭-执行标志的描述符会自动关闭。
将打开的(例如,私有)文件上的文件描述符泄漏到外部程序通常是一个安全漏洞:然后,程序可以访问私有文件并对其进行恶意操作。因此,强烈建议设置所有文件描述符“关闭-执行”,除了在极少数情况下需要将文件描述符实际传输到另一个程序。
设置文件描述符“关闭-执行”的最佳方法是以这种状态创建它。为此,openfile
函数具有 O_CLOEXEC
和 O_KEEPEXEC
标志,分别用于强制执行“关闭-执行”模式或“保持-执行”模式。Unix 模块中创建文件描述符的所有其他操作都有一个可选参数 ?cloexec:bool
,用于指示是否应在“关闭-执行”模式(通过写入 ~cloexec:true
)或“保持-执行”模式(通过写入 ~cloexec:false
)下创建文件描述符。出于历史原因,如果未给出 cloexec
可选参数,则默认文件描述符创建模式为“保持-执行”。这不是一个安全的默认值,因此强烈建议将显式 cloexec
参数传递给创建文件描述符的操作。
cloexec
可选参数和 O_KEEPEXEC
标志是在 OCaml 4.05 中引入的。在此之前,常见的做法是在默认的“保持-执行”模式下创建文件描述符,然后在这些新创建的文件描述符上调用 set_close_on_exec
。这不如在“关闭-执行”模式下创建文件描述符安全,因为在多线程程序中,在创建文件描述符的时间和 set_close_on_exec
完成的时间之间存在一个漏洞窗口。如果另一个线程在此窗口期间生成另一个程序,则描述符将泄漏,因为它仍然处于“保持-执行”模式。
关于 ~cloexec:true
或使用 O_CLOEXEC
标志提供的原子性保证:在所有平台上,都保证并发执行的 Caml 线程无法通过启动新进程来泄漏描述符。在 Linux 上,此保证扩展到并发执行的 C 线程。截至 2017 年 2 月,其他操作系统缺少必要的系统调用,并且仍然存在一个漏洞窗口,在此期间 C 线程可以看到新创建的文件描述符处于“保持-执行”模式。
val clear_close_on_exec : file_descr -> unit
清除给定描述符上的“关闭-执行”标志。请参阅 Unix.set_close_on_exec
。
val mkdir : string -> file_perm -> unit
使用给定的权限创建目录(请参阅 Unix.umask
)。
val rmdir : string -> unit
删除空目录。
val chdir : string -> unit
更改进程的工作目录。
val getcwd : unit -> string
返回当前工作目录的名称。
val chroot : string -> unit
更改进程的根目录。
Invalid_argument
异常type
dir_handle
已打开目录上的描述符类型。
val opendir : string -> dir_handle
在目录上打开一个描述符
val readdir : dir_handle -> string
返回目录中的下一个条目。
End_of_file
,当到达目录的末尾时。val rewinddir : dir_handle -> unit
将描述符重新定位到目录的开头
val closedir : dir_handle -> unit
关闭目录描述符。
val pipe : ?cloexec:bool -> unit -> file_descr * file_descr
创建管道。结果的第一个组件用于读取,这是管道的出口。第二个组件用于写入,这是管道的入口。有关可选参数 cloexec
的文档,请参阅 Unix.set_close_on_exec
。
val mkfifo : string -> file_perm -> unit
使用给定的权限创建命名管道(请参阅 Unix.umask
)。
Invalid_argument
异常val create_process : string ->
string array -> file_descr -> file_descr -> file_descr -> int
create_process prog args stdin stdout stderr
创建一个新的进程,执行文件 prog
中的程序,并带参数 args
。请注意,第一个参数 args.(0)
按照惯例是正在执行的程序的文件名,就像 Sys.argv.(0)
一样。新进程的 pid 会立即返回;新进程与当前进程并发执行。新进程的标准输入和输出连接到描述符 stdin
、stdout
和 stderr
。例如,将 Unix.stdout
传递给 stdout
会阻止重定向,并导致新进程与当前进程具有相同的标准输出。可执行文件 prog
会在路径中搜索。新进程与当前进程具有相同的环境。
val create_process_env : string ->
string array ->
string array -> file_descr -> file_descr -> file_descr -> int
create_process_env prog args env stdin stdout stderr
的工作方式与 Unix.create_process
相同,除了额外的参数 env
指定传递给程序的环境。
val open_process_in : string -> in_channel
高级管道和进程管理。此函数并行运行给定的命令和程序。命令的标准输出重定向到一个管道,可以通过返回的输入通道读取。命令由 shell /bin/sh
(或 Windows 上的 cmd.exe
)解释,参见 Unix.system
。 Filename.quote_command
函数可用于根据所使用的 shell 对命令及其参数进行适当的引用。如果命令不需要通过 shell 运行,则可以使用 Unix.open_process_args_in
作为 Unix.open_process_in
的更健壮、更高效的替代方案。
val open_process_out : string -> out_channel
与 Unix.open_process_in
相同,但将命令的标准输入重定向到一个管道。写入返回的输出通道的数据将发送到命令的标准输入。警告:输出通道上的写入是缓冲的,因此请注意在正确的时间调用 flush
以确保正确的同步。如果命令不需要通过 shell 运行,则可以使用 Unix.open_process_args_out
而不是 Unix.open_process_out
。
val open_process : string -> in_channel * out_channel
与 Unix.open_process_out
相同,但将命令的标准输入和标准输出都重定向到连接到两个返回通道的管道。输入通道连接到命令的输出,输出通道连接到命令的输入。如果命令不需要通过 shell 运行,则可以使用 Unix.open_process_args
而不是 Unix.open_process
。
val open_process_full : string ->
string array -> in_channel * out_channel * in_channel
类似于 Unix.open_process
,但第二个参数指定传递给命令的环境。结果是三个通道,分别连接到命令的标准输出、标准输入和标准错误。如果命令不需要通过 shell 运行,则可以使用 Unix.open_process_args_full
而不是 Unix.open_process_full
。
val open_process_args : string -> string array -> in_channel * out_channel
open_process_args prog args
运行程序 prog
及其参数 args
。请注意,第一个参数 args.(0)
按照惯例是正在执行的程序的文件名,就像 Sys.argv.(0)
一样。新进程与当前进程并发执行。新进程的标准输入和输出重定向到管道,可以通过返回的通道分别读取和写入。输入通道连接到程序的输出,输出通道连接到程序的输入。
警告:输出通道上的写入是缓冲的,因此请注意在正确的时间调用 flush
以确保正确的同步。
在路径中搜索可执行文件 prog
。此行为在 4.12 中发生了变化;之前 prog
仅在当前目录中查找。
新进程与当前进程具有相同的环境。
val open_process_args_in : string -> string array -> in_channel
与 Unix.open_process_args
相同,但仅重定向新进程的标准输出。
val open_process_args_out : string -> string array -> out_channel
与 Unix.open_process_args
相同,但仅重定向新进程的标准输入。
val open_process_args_full : string ->
string array ->
string array -> in_channel * out_channel * in_channel
类似于 Unix.open_process_args
,但第三个参数指定传递给新进程的环境。结果是三个通道,分别连接到程序的标准输出、标准输入和标准错误。
val process_in_pid : in_channel -> int
返回通过 Unix.open_process_args_in
打开的进程的 pid 或通过 Unix.open_process_in
打开的 shell 的 pid。
val process_out_pid : out_channel -> int
返回通过 Unix.open_process_args_out
打开的进程的 pid 或通过 Unix.open_process_out
打开的 shell 的 pid。
val process_pid : in_channel * out_channel -> int
返回通过 Unix.open_process_args
打开的进程的 pid 或通过 Unix.open_process_args
打开的 shell 的 pid。
val process_full_pid : in_channel * out_channel * in_channel -> int
返回通过 Unix.open_process_args_full
打开的进程的 pid 或通过 Unix.open_process_full
打开的 shell 的 pid。
val close_process_in : in_channel -> process_status
关闭由 Unix.open_process_in
打开的通道,等待关联的命令终止,并返回其终止状态。
val close_process_out : out_channel -> process_status
关闭由 Unix.open_process_out
打开的通道,等待关联的命令终止,并返回其终止状态。
val close_process : in_channel * out_channel -> process_status
关闭由 Unix.open_process
打开的通道,等待关联的命令终止,并返回其终止状态。
val close_process_full : in_channel * out_channel * in_channel ->
process_status
关闭由 Unix.open_process_full
打开的通道,等待关联的命令终止,并返回其终止状态。
val symlink : ?to_dir:bool -> string -> string -> unit
symlink ?to_dir src dst
创建文件 dst
作为文件 src
的符号链接。在 Windows 上,~to_dir
指示符号链接指向目录还是文件;如果省略,symlink
将使用 stat
检查 src
并适当地选择,如果 src
不存在,则假定为 false
(因此,建议在新代码中指定 ~to_dir
参数)。在 Unix 上,忽略 ~to_dir
。
Windows 符号链接在 Windows Vista 及更高版本中可用。Windows 符号链接与其 POSIX 对应项之间存在一些重要区别。
Windows 符号链接有两种类型:目录和普通文件,它们分别指定符号链接指向目录还是文件。类型必须正确 - 实际上指向文件的目录符号链接不能与 chdir 一起选择,而实际上指向目录的文件符号链接不能读取或写入(请注意,Cygwin 的模拟层忽略了这种区别)。
当创建到现有目标的符号链接时,这种区别无关紧要,symlink
将自动创建正确类型的符号链接。当创建到不存在的目标的符号链接时,这种区别很重要。
另一个注意事项是,默认情况下,符号链接是一种特权操作。管理员始终需要以提升的权限运行(或禁用 UAC),并且默认情况下,需要通过本地安全策略 (secpol.msc) 或通过 Active Directory 向普通用户帐户授予 SeCreateSymbolicLinkPrivilege。
Unix.has_symlink
可用于检查进程是否能够创建符号链接。
val has_symlink : unit -> bool
如果用户能够创建符号链接,则返回 true
。在 Windows 上,这表示用户不仅拥有 SeCreateSymbolicLinkPrivilege,而且还在必要时以提升的权限运行。在其他平台上,这仅表示符号链接系统调用可用。
val readlink : string -> string
读取符号链接的内容。
val select : file_descr list ->
file_descr list ->
file_descr list ->
float -> file_descr list * file_descr list * file_descr list
等待某些输入/输出操作在某些通道上变得可能。这三个列表参数分别是:一组要检查读取的描述符(第一个参数)、要检查写入的描述符(第二个参数)或要检查异常情况的描述符(第三个参数)。第四个参数是最大超时时间(以秒为单位);负的第四个参数表示没有超时(无限等待)。结果由三组描述符组成:准备读取的描述符(第一个组件)、准备写入的描述符(第二个组件)以及正在等待异常条件的描述符(第三个组件)。
type
lock_command =
| |
F_ULOCK |
(* | 解锁区域 | *) |
| |
F_LOCK |
(* | 锁定区域以进行写入,如果已锁定则阻塞 | *) |
| |
F_TLOCK |
(* | 锁定区域以进行写入,如果已锁定则失败 | *) |
| |
F_TEST |
(* | 测试区域是否存在其他进程的锁 | *) |
| |
F_RLOCK |
(* | 锁定区域以进行读取,如果已锁定则阻塞 | *) |
| |
F_TRLOCK |
(* | 锁定区域以进行读取,如果已锁定则失败 | *) |
用于 Unix.lockf
的命令。
val lockf : file_descr -> lock_command -> int -> unit
lockf fd mode len
对作为 fd
打开的文件的某个区域加锁。该区域从 fd
的当前读/写位置开始(由 Unix.lseek
设置),如果 len
为正,则向前扩展 len
个字节,如果 len
为负,则向后扩展 len
个字节,如果 len
为零,则扩展到文件末尾。写锁阻止任何其他进程获取该区域的读或写锁。读锁阻止任何其他进程获取该区域的写锁,但允许其他进程获取该区域的读锁。
F_LOCK
和 F_TLOCK
命令尝试对指定区域加写锁。 F_RLOCK
和 F_TRLOCK
命令尝试对指定区域加读锁。如果另一个进程加的锁阻止当前进程获取锁,F_LOCK
和 F_RLOCK
会阻塞,直到这些锁被移除,而 F_TLOCK
和 F_TRLOCK
会立即失败并抛出异常。 F_ULOCK
移除当前进程在指定区域上的所有锁。最后,F_TEST
命令测试是否可以在指定区域上获取写锁,而无需实际加锁。如果成功,则立即返回;否则失败。
当一个进程尝试锁定一个文件区域,而该区域已经被同一个进程锁定,会发生什么取决于操作系统。在符合 POSIX 标准的系统上,第二个锁定操作会成功,并且可能会将旧的锁从读锁提升为写锁。在 Windows 上,第二个锁定操作将阻塞或失败。
注意:信号处理程序的安装是通过函数 Sys.signal
和 Sys.set_signal
执行的。
val kill : int -> int -> unit
kill pid signal
将信号编号 signal
发送到 id 为 pid
的进程。
在 Windows 上:只模拟 Sys.sigkill
信号。
type
sigprocmask_command =
| |
SIG_SETMASK |
| |
SIG_BLOCK |
| |
SIG_UNBLOCK |
val sigprocmask : sigprocmask_command -> int list -> int list
sigprocmask mode sigs
更改被阻塞信号的集合。如果 mode
为 SIG_SETMASK
,则将被阻塞信号设置为列表 sigs
中的信号。如果 mode
为 SIG_BLOCK
,则将 sigs
中的信号添加到被阻塞信号集中。如果 mode
为 SIG_UNBLOCK
,则从被阻塞信号集中移除 sigs
中的信号。 sigprocmask
返回之前被阻塞的信号集。
当加载 Thread
模块的 systhreads 版本时,此函数会重定向到 Thread.sigmask
。即,sigprocmask
仅更改当前线程的掩码。
Invalid_argument
(Windows 上没有进程间信号)val sigpending : unit -> int list
返回当前挂起的被阻塞信号集。
Invalid_argument
(Windows 上没有进程间信号)val sigsuspend : int list -> unit
sigsuspend sigs
原子地将被阻塞信号设置为 sigs
,并等待传递一个未被忽略且未被阻塞的信号。返回时,被阻塞信号将重置为其初始值。
Invalid_argument
(Windows 上没有进程间信号)val pause : unit -> unit
等待传递一个未被忽略且未被阻塞的信号。
Invalid_argument
(Windows 上没有进程间信号)type
process_times = {
|
tms_utime : |
(* | 进程的用户时间 | *) |
|
tms_stime : |
(* | 进程的系统时间 | *) |
|
tms_cutime : |
(* | 子进程的用户时间 | *) |
|
tms_cstime : |
(* | 子进程的系统时间 | *) |
}
进程的执行时间(CPU 时间)。
type
tm = {
|
tm_sec : |
(* | 秒 0..60 | *) |
|
tm_min : |
(* | 分钟 0..59 | *) |
|
tm_hour : |
(* | 小时 0..23 | *) |
|
tm_mday : |
(* | 月份中的日期 1..31 | *) |
|
tm_mon : |
(* | 年份中的月份 0..11 | *) |
|
tm_year : |
(* | 年份 - 1900 | *) |
|
tm_wday : |
(* | 星期几(星期日为 0) | *) |
|
tm_yday : |
(* | 一年中的日期 0..365 | *) |
|
tm_isdst : |
(* | 夏令时生效 | *) |
}
表示挂钟时间和日历日期的类型。
val time : unit -> float
返回自 1970 年 1 月 1 日 00:00:00 GMT 以来当前的秒数。
val gettimeofday : unit -> float
与 Unix.time
相同,但分辨率高于 1 秒。
val gmtime : float -> tm
将 Unix.time
返回的以秒为单位的时间转换为日期和时间。假设为 UTC(协调世界时),也称为 GMT。要执行反向转换,请将 TZ 环境变量设置为“UTC”,使用 Unix.mktime
,然后恢复 TZ 的原始值。
val localtime : float -> tm
将 Unix.time
返回的以秒为单位的时间转换为日期和时间。假设为本地时区。执行反向转换的函数是 Unix.mktime
。
val mktime : tm -> float * tm
将由 tm
参数指定的日期和时间转换为 Unix.time
返回的以秒为单位的时间。 tm
的 tm_isdst
、tm_wday
和 tm_yday
字段将被忽略。还会返回给定 tm
记录的规范化副本,其中 tm_wday
、tm_yday
和 tm_isdst
字段根据其他字段重新计算,其他字段也已规范化(例如,10 月 40 日将更改为 11 月 9 日)。 tm
参数在本地时区中解释。
val alarm : int -> int
在给定秒数后安排一个 SIGALRM
信号。
Invalid_argument
异常val sleep : int -> unit
停止执行给定秒数。
val sleepf : float -> unit
停止执行给定秒数。与 sleep
相同,但支持秒的分数。
val times : unit -> process_times
返回进程的执行时间。
在 Windows 上:部分实现,不会报告子进程的计时。
val utimes : string -> float -> float -> unit
设置文件的最后访问时间(第二个参数)和最后修改时间(第三个参数)。时间以自 1970 年 1 月 1 日 00:00:00 GMT 以来秒为单位表示。如果两个时间都为 0.0
,则访问时间和最后修改时间都设置为当前时间。
type
interval_timer =
| |
ITIMER_REAL |
(* | 以实时递减,并在到期时发送信号 | *) |
| |
ITIMER_VIRTUAL |
(* | 在进程虚拟时间中递减,并在到期时发送 | *) |
| |
ITIMER_PROF |
(* | (用于分析)在进程运行时和系统代表进程运行时均递减;在到期时发送 | *) |
三种类型的间隔定时器。
type
interval_timer_status = {
|
it_interval : |
(* | 周期 | *) |
|
it_value : |
(* | 定时器的当前值 | *) |
}
描述间隔定时器状态的类型
val getitimer : interval_timer -> interval_timer_status
返回给定间隔定时器的当前状态。
Invalid_argument
异常val setitimer : interval_timer ->
interval_timer_status -> interval_timer_status
setitimer t s
设置间隔定时器 t
并返回其先前状态。 s
参数的解释如下: s.it_value
(如果非零)是到下一个定时器到期的时间; s.it_interval
(如果非零)指定一个值,用于在定时器到期时重新加载 it_value
。将 s.it_value
设置为零将禁用定时器。将 s.it_interval
设置为零会导致定时器在下次到期后被禁用。
Invalid_argument
异常val getuid : unit -> int
返回执行进程的用户 ID。
在 Windows 上:始终返回 1
。
val geteuid : unit -> int
返回进程运行的有效用户 ID。
在 Windows 上:始终返回 1
。
val setuid : int -> unit
设置进程的真实用户 ID 和有效用户 ID。
Invalid_argument
异常val getgid : unit -> int
返回执行进程的用户组 ID。
在 Windows 上:始终返回 1
。
val getegid : unit -> int
返回进程运行的有效组 ID。
在 Windows 上:始终返回 1
。
val setgid : int -> unit
设置进程的真实组 ID 和有效组 ID。
Invalid_argument
异常val getgroups : unit -> int array
返回执行进程的用户所属的组列表。
在 Windows 上:始终返回 [|1|]
。
val setgroups : int array -> unit
setgroups groups
设置调用进程的补充组 ID。需要适当的权限。
Invalid_argument
异常val initgroups : string -> int -> unit
initgroups user group
通过读取组数据库 /etc/group 并使用 user
是其成员的所有组来初始化组访问列表。 group
附加组也将添加到列表中。
Invalid_argument
异常type
passwd_entry = {
|
pw_name : |
|
pw_passwd : |
|
pw_uid : |
|
pw_gid : |
|
pw_gecos : |
|
pw_dir : |
|
pw_shell : |
}
passwd
数据库中条目的结构。
type
group_entry = {
|
gr_name : |
|
gr_passwd : |
|
gr_gid : |
|
gr_mem : |
}
groups
数据库中条目的结构。
val getlogin : unit -> string
返回执行进程的用户登录名。
val getpwnam : string -> passwd_entry
在 passwd
中查找具有给定名称的条目。
Not_found
,或者在 Windows 上始终引发。val getgrnam : string -> group_entry
在 group
中查找具有给定名称的条目。
Not_found
,或者在 Windows 上始终引发。val getpwuid : int -> passwd_entry
在 passwd
中查找具有给定用户 ID 的条目。
Not_found
,或者在 Windows 上始终引发。val getgrgid : int -> group_entry
在 group
中查找具有给定组 ID 的条目。
Not_found
,或者在 Windows 上始终引发。type
inet_addr
Internet 地址的抽象类型。
val inet_addr_of_string : string -> inet_addr
将 Internet 地址的可打印表示形式转换为其内部表示形式。参数字符串由用句点分隔的 4 个数字组成(XXX.YYY.ZZZ.TTT
)表示 IPv4 地址,以及用冒号分隔的多达 8 个数字表示 IPv6 地址。
Failure
。val string_of_inet_addr : inet_addr -> string
返回给定 Internet 地址的可打印表示形式。有关可打印表示形式的说明,请参阅 Unix.inet_addr_of_string
。
val inet_addr_any : inet_addr
一个特殊的 IPv4 地址,仅用于 bind
,表示主机拥有的所有 Internet 地址。
val inet_addr_loopback : inet_addr
表示主机(127.0.0.1
)的特殊 IPv4 地址。
val inet6_addr_any : inet_addr
一个特殊的 IPv6 地址,仅用于 bind
,表示主机拥有的所有 Internet 地址。
val inet6_addr_loopback : inet_addr
表示主机机器的一个特殊 IPv6 地址(::1
)。
val is_inet6_addr : inet_addr -> bool
给定的 inet_addr
是否为 IPv6 地址。
type
socket_domain =
| |
PF_UNIX |
(* | Unix 域 | *) |
| |
PF_INET |
(* | 互联网域 (IPv4) | *) |
| |
PF_INET6 |
(* | 互联网域 (IPv6) | *) |
套接字域的类型。并非所有平台都支持 IPv6 套接字(类型 PF_INET6
)。
在 Windows 上:PF_UNIX
在 Windows 10 1803 及更高版本上的 4.14.0 版本开始支持。
type
socket_type =
| |
SOCK_STREAM |
(* | 流式套接字 | *) |
| |
SOCK_DGRAM |
(* | 数据报套接字 | *) |
| |
SOCK_RAW |
(* | 原始套接字 | *) |
| |
SOCK_SEQPACKET |
(* | 顺序数据包套接字 | *) |
套接字类型的类型,指定通信的语义。 SOCK_SEQPACKET
包含在内是为了完整性,但很少受操作系统支持,并且需要此库中不可用的系统调用。
type
sockaddr =
| |
ADDR_UNIX of |
| |
ADDR_INET of |
套接字地址的类型。 ADDR_UNIX name
是 Unix 域中的套接字地址;name
是文件系统中的文件名。 ADDR_INET(addr,port)
是互联网域中的套接字地址;addr
是机器的互联网地址,port
是端口号。
val socket : ?cloexec:bool ->
socket_domain -> socket_type -> int -> file_descr
在给定的域中并使用给定的类型创建一个新的套接字。第三个参数是协议类型;0 选择该类型套接字的默认协议。有关 cloexec
可选参数的文档,请参阅 Unix.set_close_on_exec
。
val domain_of_sockaddr : sockaddr -> socket_domain
返回适合给定套接字地址的套接字域。
val socketpair : ?cloexec:bool ->
socket_domain ->
socket_type -> int -> file_descr * file_descr
创建一对无名套接字,它们彼此连接。有关 cloexec
可选参数的文档,请参阅 Unix.set_close_on_exec
。
val accept : ?cloexec:bool -> file_descr -> file_descr * sockaddr
接受给定套接字上的连接。返回的描述符是与客户端连接的套接字;返回的地址是连接客户端的地址。有关 cloexec
可选参数的文档,请参阅 Unix.set_close_on_exec
。
val bind : file_descr -> sockaddr -> unit
将套接字绑定到地址。
val connect : file_descr -> sockaddr -> unit
将套接字连接到地址。
val listen : file_descr -> int -> unit
设置套接字以接收连接请求。整数参数是挂起的最大请求数。
type
shutdown_command =
| |
SHUTDOWN_RECEIVE |
(* | 关闭接收 | *) |
| |
SHUTDOWN_SEND |
(* | 关闭发送 | *) |
| |
SHUTDOWN_ALL |
(* | 同时关闭 | *) |
shutdown
命令的类型。
val shutdown : file_descr -> shutdown_command -> unit
关闭套接字连接。将 SHUTDOWN_SEND
作为第二个参数会导致连接另一端的读取返回文件结束条件。 SHUTDOWN_RECEIVE
会导致连接另一端的写入返回管道已关闭条件(SIGPIPE
信号)。
val getsockname : file_descr -> sockaddr
返回给定套接字的地址。
val getpeername : file_descr -> sockaddr
返回连接到给定套接字的主机的地址。
type
msg_flag =
| |
MSG_OOB |
| |
MSG_DONTROUTE |
| |
MSG_PEEK |
val recv : file_descr -> bytes -> int -> int -> msg_flag list -> int
从已连接的套接字接收数据。
val recvfrom : file_descr ->
bytes -> int -> int -> msg_flag list -> int * sockaddr
从未连接的套接字接收数据。
val send : file_descr -> bytes -> int -> int -> msg_flag list -> int
通过已连接的套接字发送数据。
val send_substring : file_descr -> string -> int -> int -> msg_flag list -> int
与 send
相同,但从字符串而不是字节序列中获取数据。
val sendto : file_descr ->
bytes -> int -> int -> msg_flag list -> sockaddr -> int
通过未连接的套接字发送数据。
val sendto_substring : file_descr ->
string -> int -> int -> msg_flag list -> sockaddr -> int
与 sendto
相同,但从字符串而不是字节序列中获取数据。
type
socket_bool_option =
| |
SO_DEBUG |
(* | 记录调试信息 | *) |
| |
SO_BROADCAST |
(* | 允许发送广播消息 | *) |
| |
SO_REUSEADDR |
(* | 允许重用本地地址进行绑定 | *) |
| |
SO_KEEPALIVE |
(* | 保持连接活动 | *) |
| |
SO_DONTROUTE |
(* | 绕过标准路由算法 | *) |
| |
SO_OOBINLINE |
(* | 将带外数据保留在线上 | *) |
| |
SO_ACCEPTCONN |
(* | 报告套接字侦听是否启用 | *) |
| |
TCP_NODELAY |
(* | 控制 TCP 套接字的 Nagle 算法 | *) |
| |
IPV6_ONLY |
(* | 禁止将 IPv6 套接字绑定到 IPv4 地址 | *) |
| |
SO_REUSEPORT |
(* | 允许重用地址和端口绑定 | *) |
可以使用 Unix.getsockopt
查询并使用 Unix.setsockopt
修改的套接字选项。这些选项具有布尔值(true
/false
)。
type
socket_int_option =
| |
SO_SNDBUF |
(* | 发送缓冲区的大小 | *) |
| |
SO_RCVBUF |
(* | 接收缓冲区的大小 | *) |
| |
SO_ERROR |
(* |
已弃用。 请改用 Unix.getsockopt_error。
已弃用。请改用 | *) |
| |
SO_TYPE |
(* | 报告套接字类型 | *) |
| |
SO_RCVLOWAT |
(* | 输入操作要处理的最小字节数 | *) |
| |
SO_SNDLOWAT |
(* | 输出操作要处理的最小字节数 | *) |
可以使用 Unix.getsockopt_int
查询并使用 Unix.setsockopt_int
修改的套接字选项。这些选项具有整数值。
type
socket_optint_option =
| |
SO_LINGER |
(* | 是否在存在数据的已关闭连接上保持连接,以及保持多长时间(以秒为单位) | *) |
可以使用 Unix.getsockopt_optint
查询并使用 Unix.setsockopt_optint
修改的套接字选项。这些选项的值为类型 int option
,其中 None
表示“禁用”。
type
socket_float_option =
| |
SO_RCVTIMEO |
(* | 输入操作的超时时间 | *) |
| |
SO_SNDTIMEO |
(* | 输出操作的超时时间 | *) |
可以使用 Unix.getsockopt_float
查询并使用 Unix.setsockopt_float
修改的套接字选项。这些选项具有表示以秒为单位的时间的浮点值。值为 0 表示无限超时。
val getsockopt : file_descr -> socket_bool_option -> bool
返回给定套接字中布尔值选项的当前状态。
val setsockopt : file_descr -> socket_bool_option -> bool -> unit
设置或清除给定套接字中布尔值选项。
val getsockopt_int : file_descr -> socket_int_option -> int
与整数值套接字选项的 Unix.getsockopt
相同。
val setsockopt_int : file_descr -> socket_int_option -> int -> unit
与整数值套接字选项的 Unix.setsockopt
相同。
val getsockopt_optint : file_descr -> socket_optint_option -> int option
与值是 int option
的套接字选项的 Unix.getsockopt
相同。
val setsockopt_optint : file_descr -> socket_optint_option -> int option -> unit
与值是 int option
的套接字选项的 Unix.setsockopt
相同。
val getsockopt_float : file_descr -> socket_float_option -> float
与值是浮点数的套接字选项的 Unix.getsockopt
相同。
val setsockopt_float : file_descr -> socket_float_option -> float -> unit
与值是浮点数的套接字选项的 Unix.setsockopt
相同。
val getsockopt_error : file_descr -> error option
返回与给定套接字关联的错误条件,并将其清除。
val open_connection : sockaddr -> in_channel * out_channel
val shutdown_connection : in_channel -> unit
“关闭”使用 Unix.open_connection
建立的连接;也就是说,向连接另一端读取的服务器发送文件结束条件。这不会关闭套接字和连接使用的通道。有关连接结束后如何关闭它们,请参阅 Unix.open_connection
。
val establish_server : (in_channel -> out_channel -> unit) -> sockaddr -> unit
在给定地址上建立服务器。作为第一个参数给出的函数将为每个连接调用两次连接到客户端的缓冲通道。为每个连接创建一个新进程。函数 Unix.establish_server
从不正常返回。
给定函数的两个通道共享套接字的描述符。函数不需要关闭通道,因为这会在函数返回时自动发生。如果函数更喜欢显式关闭,它应该使用 close_out
关闭输出通道,并将输入通道保持未关闭状态,原因在 Unix.in_channel_of_descr
中解释。
Invalid_argument
。请改用线程。type
host_entry = {
|
h_name : |
|
h_aliases : |
|
h_addrtype : |
|
h_addr_list : |
}
hosts
数据库中条目的结构。
type
protocol_entry = {
|
p_name : |
|
p_aliases : |
|
p_proto : |
}
protocols
数据库中条目的结构。
type
service_entry = {
|
s_name : |
|
s_aliases : |
|
s_port : |
|
s_proto : |
}
services
数据库中条目的结构。
val gethostname : unit -> string
返回本地主机名。
val gethostbyname : string -> host_entry
在 hosts
中查找具有给定名称的条目。
Not_found
。val gethostbyaddr : inet_addr -> host_entry
在 hosts
中查找具有给定地址的条目。
Not_found
。val getprotobyname : string -> protocol_entry
在 protocols
中查找具有给定名称的条目。
Not_found
。val getprotobynumber : int -> protocol_entry
在 protocols
中查找具有给定协议号的条目。
Not_found
。val getservbyname : string -> string -> service_entry
在 services
中查找具有给定名称的条目。
Not_found
。val getservbyport : int -> string -> service_entry
在 services
中查找具有给定服务号的条目。
Not_found
。type
addr_info = {
|
ai_family : |
(* | 套接字域 | *) |
|
ai_socktype : |
(* | 套接字类型 | *) |
|
ai_protocol : |
(* | 套接字协议号 | *) |
|
ai_addr : |
(* | 地址 | *) |
|
ai_canonname : |
(* | 规范主机名 | *) |
}
由 Unix.getaddrinfo
返回的地址信息。
type
getaddrinfo_option =
| |
AI_FAMILY of |
(* | 强制使用指定的套接字域 | *) |
| |
AI_SOCKTYPE of |
(* | 强制使用指定的套接字类型 | *) |
| |
AI_PROTOCOL of |
(* | 强制使用指定的协议 | *) |
| |
AI_NUMERICHOST |
(* | 不调用名称解析器,期望数值型 IP 地址 | *) |
| |
AI_CANONNAME |
(* | 填充结果的 | *) |
| |
AI_PASSIVE |
(* | 将地址设置为“任意”地址,用于 | *) |
传递给 Unix.getaddrinfo
的选项。
val getaddrinfo : string -> string -> getaddrinfo_option list -> addr_info list
getaddrinfo host service opts
返回一个 Unix.addr_info
记录列表,这些记录描述了适合与给定主机和服务通信的套接字参数和地址。如果主机名或服务名未知,或者 opts
中表达的约束条件无法满足,则返回空列表。
host
可以是主机名或 IP 地址的字符串表示形式。 host
可以为空字符串;在这种情况下,将使用“任意”地址或“环回”地址,具体取决于 opts
是否包含 AI_PASSIVE
。 service
可以是服务名或端口号的字符串表示形式。 service
可以为空字符串;在这种情况下,返回地址的端口字段将设置为 0。 opts
是一个可能为空的选项列表,允许调用方强制使用特定的套接字域(例如,仅 IPv6 或仅 IPv4)或特定的套接字类型(例如,仅 TCP 或仅 UDP)。
type
name_info = {
|
ni_hostname : |
(* | 主机名或 IP 地址 | *) |
|
ni_service : |
(* | 服务名或端口号 | *) |
}
由 Unix.getnameinfo
返回的主机和服务信息。
type
getnameinfo_option =
| |
NI_NOFQDN |
(* | 不要限定本地主机名 | *) |
| |
NI_NUMERICHOST |
(* | 始终将主机作为 IP 地址返回 | *) |
| |
NI_NAMEREQD |
(* | 如果无法确定主机名,则失败 | *) |
| |
NI_NUMERICSERV |
(* | 始终将服务作为端口号返回 | *) |
| |
NI_DGRAM |
(* | 将服务视为基于 UDP 而不是默认的 TCP | *) |
传递给 Unix.getnameinfo
的选项。
val getnameinfo : sockaddr -> getnameinfo_option list -> name_info
getnameinfo addr opts
返回与套接字地址 addr
对应的主机名和服务名。 opts
是一个可能为空的选项列表,用于控制如何获取这些名称。
Not_found
,如果发生错误。以下函数实现了 POSIX 标准终端接口。它们提供了对异步通信端口和伪终端的控制。有关完整说明,请参阅 termios
手册页。
type
terminal_io = {
|
mutable c_ignbrk : |
(* | 忽略中断条件。 | *) |
|
mutable c_brkint : |
(* | 在中断条件下发送中断信号。 | *) |
|
mutable c_ignpar : |
(* | 忽略奇偶校验错误的字符。 | *) |
|
mutable c_parmrk : |
(* | 标记奇偶校验错误。 | *) |
|
mutable c_inpck : |
(* | 启用输入的奇偶校验检查。 | *) |
|
mutable c_istrip : |
(* | 剥离输入字符的第 8 位。 | *) |
|
mutable c_inlcr : |
(* | 将 NL 映射到输入的 CR。 | *) |
|
mutable c_igncr : |
(* | 忽略输入的 CR。 | *) |
|
mutable c_icrnl : |
(* | 将 CR 映射到输入的 NL。 | *) |
|
mutable c_ixon : |
(* | 识别输入的 XON/XOFF 字符。 | *) |
|
mutable c_ixoff : |
(* | 发出 XON/XOFF 字符以控制输入流。 | *) |
|
mutable c_opost : |
(* | 启用输出处理。 | *) |
|
mutable c_obaud : |
(* | 输出波特率(0 表示关闭连接)。 | *) |
|
mutable c_ibaud : |
(* | 输入波特率。 | *) |
|
mutable c_csize : |
(* | 每个字符的位数(5-8)。 | *) |
|
mutable c_cstopb : |
(* | 停止位的数量(1-2)。 | *) |
|
mutable c_cread : |
(* | 接收已启用。 | *) |
|
mutable c_parenb : |
(* | 启用奇偶校验生成和检测。 | *) |
|
mutable c_parodd : |
(* | 指定奇校验而不是偶校验。 | *) |
|
mutable c_hupcl : |
(* | 在最后一次关闭时挂断。 | *) |
|
mutable c_clocal : |
(* | 忽略调制解调器状态行。 | *) |
|
mutable c_isig : |
(* | 在 INTR、QUIT、SUSP 上生成信号。 | *) |
|
mutable c_icanon : |
(* | 启用规范处理(行缓冲和编辑) | *) |
|
mutable c_noflsh : |
(* | 禁用在 INTR、QUIT、SUSP 之后刷新。 | *) |
|
mutable c_echo : |
(* | 回显输入字符。 | *) |
|
mutable c_echoe : |
(* | 回显 ERASE(以擦除前一个字符)。 | *) |
|
mutable c_echok : |
(* | 回显 KILL(以擦除当前行)。 | *) |
|
mutable c_echonl : |
(* | 即使未设置 c_echo 也回显 NL。 | *) |
|
mutable c_vintr : |
(* | 中断字符(通常为 ctrl-C)。 | *) |
|
mutable c_vquit : |
(* | 退出字符(通常为 ctrl-\)。 | *) |
|
mutable c_verase : |
(* | 擦除字符(通常为 DEL 或 ctrl-H)。 | *) |
|
mutable c_vkill : |
(* | 删除行字符(通常为 ctrl-U)。 | *) |
|
mutable c_veof : |
(* | 文件结束字符(通常为 ctrl-D)。 | *) |
|
mutable c_veol : |
(* | 备用换行符。(通常为无)。 | *) |
|
mutable c_vmin : |
(* | 在读取请求满足之前要读取的最小字符数。 | *) |
|
mutable c_vtime : |
(* | 最大读取等待时间(以 0.1 秒为单位)。 | *) |
|
mutable c_vstart : |
(* | 启动字符(通常为 ctrl-Q)。 | *) |
|
mutable c_vstop : |
(* | 停止字符(通常为 ctrl-S)。 | *) |
}
val tcgetattr : file_descr -> terminal_io
返回由给定文件描述符引用的终端的状态。
Invalid_argument
异常type
setattr_when =
| |
TCSANOW |
| |
TCSADRAIN |
| |
TCSAFLUSH |
val tcsetattr : file_descr -> setattr_when -> terminal_io -> unit
设置由给定文件描述符引用的终端的状态。第二个参数指示状态更改何时发生:立即(TCSANOW
)、所有挂起的输出都已传输后(TCSADRAIN
),或者在刷新所有已接收但尚未读取的输入后(TCSAFLUSH
)。在更改输出参数时建议使用 TCSADRAIN
;在更改输入参数时建议使用 TCSAFLUSH
。
Invalid_argument
异常val tcsendbreak : file_descr -> int -> unit
在给定文件描述符上发送中断条件。第二个参数是中断的持续时间,以 0.1 秒为单位;0 表示标准持续时间(0.25 秒)。
Invalid_argument
异常val tcdrain : file_descr -> unit
等待直到写入给定文件描述符的所有输出都已传输。
Invalid_argument
异常type
flush_queue =
| |
TCIFLUSH |
| |
TCOFLUSH |
| |
TCIOFLUSH |
val tcflush : file_descr -> flush_queue -> unit
丢弃写入给定文件描述符但尚未传输的数据,或接收但尚未读取的数据,具体取决于第二个参数:TCIFLUSH
刷新接收但尚未读取的数据,TCOFLUSH
刷新写入但尚未传输的数据,TCIOFLUSH
刷新两者。
Invalid_argument
异常type
flow_action =
| |
TCOOFF |
| |
TCOON |
| |
TCIOFF |
| |
TCION |
val tcflow : file_descr -> flow_action -> unit
暂停或重新启动给定文件描述符上的数据接收或传输,具体取决于第二个参数:TCOOFF
暂停输出,TCOON
重新启动输出,TCIOFF
传输 STOP 字符以暂停输入,TCION
传输 START 字符以重新启动输入。
Invalid_argument
异常val setsid : unit -> int
将调用进程置于新的会话中,并将其与其控制终端分离。
Invalid_argument
异常