模块 Unix

module Unix: sig .. end

Unix 系统的接口。

要使用此模块的带标签版本,请在您的实现中添加 module Unix = UnixLabels

注意:此模块的所有函数(除了 Unix.error_messageUnix.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 int (*

未知错误

*)

错误代码的类型。POSIX 标准中定义的错误以及来自 UNIX98 和 BSD 的其他错误。所有其他错误都映射到 EUNKNOWNERR。

exception Unix_error of error * string * string

当遇到错误时,以下系统调用会引发此异常。第一个组件是错误代码;第二个组件是函数名称;第三个组件是函数的字符串参数(如果存在),否则为空字符串。

UnixLabels.Unix_errorUnix.Unix_error 是相同的,捕获其中一个将捕获另一个。

val error_message : error -> string

返回描述给定错误代码的字符串。

val handle_unix_error : ('a -> 'b) -> 'a -> 'b

handle_unix_error f xf 应用于 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

返回与进程环境中变量关联的值,除非进程具有特殊权限。

val unsafe_getenv : string -> string

返回与进程环境中变量关联的值。

Unix.getenv 不同,即使进程具有特殊权限,此函数也会返回值。它被认为是不安全的,因为 setuid 或 setgid 程序的程序员必须小心避免在可执行文件的搜索路径、临时文件或日志的位置等中使用恶意构建的环境变量。

val putenv : string -> string -> unit

putenv name value 设置与进程环境中变量关联的值。name 是环境变量的名称,value 是其新的关联值。

进程处理

type process_status = 
| WEXITED of int (*

进程通过 exit 正确终止;参数是返回代码。

*)
| WSIGNALED of int (*

进程被信号杀死;参数是信号编号。

*)
| WSTOPPED of int (*

进程被信号停止;参数是信号编号。

*)

进程的终止状态。有关标准信号编号的定义,请参阅模块 Sys。请注意,它们不是操作系统使用的编号。

在 Windows 上:仅使用 WEXITED(因为没有进程间信号),但使用特定的返回代码来指示特殊的终止原因。请在 Windows 文档中查找 NTSTATUS 值以解码此类错误返回代码。特别是,STATUS_ACCESS_VIOLATION 错误代码是 32 位 0xC0000005:由于 Int32.of_int 0xC0000005-1073741819WEXITED -1073741819WSIGNALED 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_processopen_process_* 函数之一。

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 模块中的任何线程已被生成,则子进程可能处于损坏状态。

val wait : unit -> int * process_status

等待其中一个子进程死亡,并返回其进程 ID 和终止状态。

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。

val nice : int -> int

更改进程优先级。整数参数将添加到“nice”值中。(“nice”值越高,优先级越低。)返回新的 nice 值。

基本文件输入/输出

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 (*

Unix.openfile 返回的描述符上设置 close-on-exec 标志。有关更多信息,请参阅 Unix.set_close_on_exec

*)
| O_KEEPEXEC (*

清除 close-on-exec 标志。这目前是默认设置。

*)

传递给 Unix.openfile 的标志。

type file_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 lenlen 个字节写入描述符 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 soc = 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 : int; (*

设备号

*)
   st_ino : int; (*

索引节点号

*)
   st_kind : file_kind; (*

文件的种类

*)
   st_perm : file_perm; (*

访问权限

*)
   st_nlink : int; (*

链接数

*)
   st_uid : int; (*

所有者的用户 ID

*)
   st_gid : int; (*

文件所属组的组 ID

*)
   st_rdev : int; (*

设备 ID(如果是特殊文件)

*)
   st_size : int; (*

大小(以字节为单位)

*)
   st_atime : float; (*

上次访问时间

*)
   st_mtime : float; (*

上次修改时间

*)
   st_ctime : float; (*

上次状态更改时间

*)
}

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(从文件开头映射)。

如果 sharedtrue,则对数组执行的所有修改都会反映在文件中。这要求 fd 以写权限打开。如果 sharedfalse,则对数组执行的修改仅在内存中进行,使用修改页面的写时复制;基础文件不受影响。

Unix.map_file 比将整个文件读入 Bigarray、修改该 Bigarray 然后将其写回要高效得多。

要自动将 Bigarray 的维度调整为文件的实际大小,可以将主维度(即,对于具有 C 布局的数组,为第一个维度,对于具有 Fortran 布局的数组,为最后一个维度)指定为 -1。然后,Unix.map_file 根据文件的大小确定主维度。文件必须包含由非主维度确定的整数个子数组,否则会引发 Failure

如果给出了 Bigarray 的所有维度,则将文件大小与 Bigarray 的大小进行匹配。如果文件大于 Bigarray,则仅将文件的前一部分映射到 Bigarray。如果文件小于 Bigarray,则文件会自动增长到 Bigarray 的大小。这要求对 fd 具有写权限。

对数组的访问会进行边界检查,但边界由对 map_file 的初始调用确定。因此,您应该确保在访问映射文件时没有其他进程修改它,否则可能会引发 SIGBUS 信号。例如,如果文件缩小,就会发生这种情况。

在参数验证失败的情况下,可能会引发 Invalid_argumentFailure

文件名操作

val unlink : string -> unit

删除指定的文件。

如果指定的文件是目录,则引发

  • 在符合 POSIX 标准的系统上引发 EPERM
  • 在 Linux >= 2.1.132 上引发 EISDIR
  • 在 Windows 上引发 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:指示是否遵循 src 符号链接或将创建到 src 本身的硬链接。在 Unix 系统上,这是使用 linkat(2) 函数完成的。如果未提供 ?follow,则使用 link(2) 函数,其行为取决于操作系统,但可用性更广。
val realpath : string -> string

realpath pp 的绝对路径名,通过解析所有额外的 / 字符、相对路径段和符号链接获得。

文件权限和所有权

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

更改已打开文件的权限。

val chown : string -> int -> int -> unit

更改指定文件的所属用户 UID 和所属组 GID。

val fchown : file_descr -> int -> int -> unit

更改已打开文件的所属用户 UID 和所属组 GID。

val umask : file_perm -> file_perm

设置进程的文件模式创建掩码,并返回之前的掩码。

val access : string -> access_permission list -> unit

检查进程是否对指定文件具有给定的权限。

在 Windows 上:无法测试执行权限 X_OK,仅测试读取权限。

文件描述符操作

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 dstsrc 复制到 dst,如果 dst 已经打开,则将其关闭。有关可选参数 cloexec 的文档,请参阅 Unix.set_close_on_exec

val set_nonblock : file_descr -> unit

在给定的描述符上设置“非阻塞”标志。当设置了非阻塞标志时,在暂时没有可用数据的描述符上读取会引发 EAGAINEWOULDBLOCK 错误,而不是阻塞;在暂时没有写入空间的描述符上写入也会引发 EAGAINEWOULDBLOCK

val clear_nonblock : file_descr -> unit

清除给定描述符上的“非阻塞”标志。请参阅 Unix.set_nonblock

val set_close_on_exec : file_descr -> unit

在给定的描述符上设置“关闭-执行”标志。当当前进程使用 execcreate_processopen_process 函数之一启动另一个程序时,具有关闭-执行标志的描述符会自动关闭。

将打开的(例如,私有)文件上的文件描述符泄漏到外部程序通常是一个安全漏洞:然后,程序可以访问私有文件并对其进行恶意操作。因此,强烈建议设置所有文件描述符“关闭-执行”,除了在极少数情况下需要将文件描述符实际传输到另一个程序。

设置文件描述符“关闭-执行”的最佳方法是以这种状态创建它。为此,openfile 函数具有 O_CLOEXECO_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

更改进程的根目录。

type dir_handle 

已打开目录上的描述符类型。

val opendir : string -> dir_handle

在目录上打开一个描述符

val readdir : dir_handle -> string

返回目录中的下一个条目。

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)。

高级进程和重定向管理

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 会立即返回;新进程与当前进程并发执行。新进程的标准输入和输出连接到描述符 stdinstdoutstderr。例如,将 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.systemFilename.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_LOCKF_TLOCK 命令尝试对指定区域加写锁。 F_RLOCKF_TRLOCK 命令尝试对指定区域加读锁。如果另一个进程加的锁阻止当前进程获取锁,F_LOCKF_RLOCK 会阻塞,直到这些锁被移除,而 F_TLOCKF_TRLOCK 会立即失败并抛出异常。 F_ULOCK 移除当前进程在指定区域上的所有锁。最后,F_TEST 命令测试是否可以在指定区域上获取写锁,而无需实际加锁。如果成功,则立即返回;否则失败。

当一个进程尝试锁定一个文件区域,而该区域已经被同一个进程锁定,会发生什么取决于操作系统。在符合 POSIX 标准的系统上,第二个锁定操作会成功,并且可能会将旧的锁从读锁提升为写锁。在 Windows 上,第二个锁定操作将阻塞或失败。

信号

注意:信号处理程序的安装是通过函数 Sys.signalSys.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 更改被阻塞信号的集合。如果 modeSIG_SETMASK,则将被阻塞信号设置为列表 sigs 中的信号。如果 modeSIG_BLOCK,则将 sigs 中的信号添加到被阻塞信号集中。如果 modeSIG_UNBLOCK,则从被阻塞信号集中移除 sigs 中的信号。 sigprocmask 返回之前被阻塞的信号集。

当加载 Thread 模块的 systhreads 版本时,此函数会重定向到 Thread.sigmask。即,sigprocmask 仅更改当前线程的掩码。

val sigpending : unit -> int list

返回当前挂起的被阻塞信号集。

val sigsuspend : int list -> unit

sigsuspend sigs 原子地将被阻塞信号设置为 sigs,并等待传递一个未被忽略且未被阻塞的信号。返回时,被阻塞信号将重置为其初始值。

val pause : unit -> unit

等待传递一个未被忽略且未被阻塞的信号。

时间函数

type process_times = {
   tms_utime : float; (*

进程的用户时间

*)
   tms_stime : float; (*

进程的系统时间

*)
   tms_cutime : float; (*

子进程的用户时间

*)
   tms_cstime : float; (*

子进程的系统时间

*)
}

进程的执行时间(CPU 时间)。

type tm = {
   tm_sec : int; (*

秒 0..60

*)
   tm_min : int; (*

分钟 0..59

*)
   tm_hour : int; (*

小时 0..23

*)
   tm_mday : int; (*

月份中的日期 1..31

*)
   tm_mon : int; (*

年份中的月份 0..11

*)
   tm_year : int; (*

年份 - 1900

*)
   tm_wday : int; (*

星期几(星期日为 0)

*)
   tm_yday : int; (*

一年中的日期 0..365

*)
   tm_isdst : bool; (*

夏令时生效

*)
}

表示挂钟时间和日历日期的类型。

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 返回的以秒为单位的时间。 tmtm_isdsttm_wdaytm_yday 字段将被忽略。还会返回给定 tm 记录的规范化副本,其中 tm_wdaytm_ydaytm_isdst 字段根据其他字段重新计算,其他字段也已规范化(例如,10 月 40 日将更改为 11 月 9 日)。 tm 参数在本地时区中解释。

val alarm : int -> int

在给定秒数后安排一个 SIGALRM 信号。

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 (*

以实时递减,并在到期时发送信号 SIGALRM

*)
| ITIMER_VIRTUAL (*

在进程虚拟时间中递减,并在到期时发送 SIGVTALRM

*)
| ITIMER_PROF (*

(用于分析)在进程运行时和系统代表进程运行时均递减;在到期时发送 SIGPROF

*)

三种类型的间隔定时器。

type interval_timer_status = {
   it_interval : float; (*

周期

*)
   it_value : float; (*

定时器的当前值

*)
}

描述间隔定时器状态的类型

val getitimer : interval_timer -> interval_timer_status

返回给定间隔定时器的当前状态。

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 设置为零会导致定时器在下次到期后被禁用。

用户 ID,组 ID

val getuid : unit -> int

返回执行进程的用户 ID。

在 Windows 上:始终返回 1

val geteuid : unit -> int

返回进程运行的有效用户 ID。

在 Windows 上:始终返回 1

val setuid : int -> unit

设置进程的真实用户 ID 和有效用户 ID。

val getgid : unit -> int

返回执行进程的用户组 ID。

在 Windows 上:始终返回 1

val getegid : unit -> int

返回进程运行的有效组 ID。

在 Windows 上:始终返回 1

val setgid : int -> unit

设置进程的真实组 ID 和有效组 ID。

val getgroups : unit -> int array

返回执行进程的用户所属的组列表。

在 Windows 上:始终返回 [|1|]

val setgroups : int array -> unit

setgroups groups 设置调用进程的补充组 ID。需要适当的权限。

val initgroups : string -> int -> unit

initgroups user group 通过读取组数据库 /etc/group 并使用 user 是其成员的所有组来初始化组访问列表。 group 附加组也将添加到列表中。

type passwd_entry = {
   pw_name : string;
   pw_passwd : string;
   pw_uid : int;
   pw_gid : int;
   pw_gecos : string;
   pw_dir : string;
   pw_shell : string;
}

passwd 数据库中条目的结构。

type group_entry = {
   gr_name : string;
   gr_passwd : string;
   gr_gid : int;
   gr_mem : string array;
}

groups 数据库中条目的结构。

val getlogin : unit -> string

返回执行进程的用户登录名。

val getpwnam : string -> passwd_entry

passwd 中查找具有给定名称的条目。

val getgrnam : string -> group_entry

group 中查找具有给定名称的条目。

val getpwuid : int -> passwd_entry

passwd 中查找具有给定用户 ID 的条目。

val getgrgid : int -> group_entry

group 中查找具有给定组 ID 的条目。

互联网地址

type inet_addr 

Internet 地址的抽象类型。

val inet_addr_of_string : string -> inet_addr

将 Internet 地址的可打印表示形式转换为其内部表示形式。参数字符串由用句点分隔的 4 个数字组成(XXX.YYY.ZZZ.TTT)表示 IPv4 地址,以及用冒号分隔的多达 8 个数字表示 IPv6 地址。

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 string
| ADDR_INET of inet_addr * int

套接字地址的类型。 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。

已弃用。请改用 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

连接到给定地址上的服务器。返回一对连接到服务器的缓冲通道。请记住在适当的时候对输出通道调用 flush 以确保正确的同步。

open_connection 返回的两个通道共享套接字的描述符。因此,当连接结束时,您应该对输出通道调用 close_out,这也会关闭底层套接字。不要对输入通道调用 close_in;它最终会被 GC 收集。

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 中解释。

主机和协议数据库

type host_entry = {
   h_name : string;
   h_aliases : string array;
   h_addrtype : socket_domain;
   h_addr_list : inet_addr array;
}

hosts 数据库中条目的结构。

type protocol_entry = {
   p_name : string;
   p_aliases : string array;
   p_proto : int;
}

protocols 数据库中条目的结构。

type service_entry = {
   s_name : string;
   s_aliases : string array;
   s_port : int;
   s_proto : string;
}

services 数据库中条目的结构。

val gethostname : unit -> string

返回本地主机名。

val gethostbyname : string -> host_entry

hosts 中查找具有给定名称的条目。

val gethostbyaddr : inet_addr -> host_entry

hosts 中查找具有给定地址的条目。

val getprotobyname : string -> protocol_entry

protocols 中查找具有给定名称的条目。

val getprotobynumber : int -> protocol_entry

protocols 中查找具有给定协议号的条目。

val getservbyname : string -> string -> service_entry

services 中查找具有给定名称的条目。

val getservbyport : int -> string -> service_entry

services 中查找具有给定服务号的条目。

type addr_info = {
   ai_family : socket_domain; (*

套接字域

*)
   ai_socktype : socket_type; (*

套接字类型

*)
   ai_protocol : int; (*

套接字协议号

*)
   ai_addr : sockaddr; (*

地址

*)
   ai_canonname : string; (*

规范主机名

*)
}

Unix.getaddrinfo 返回的地址信息。

type getaddrinfo_option = 
| AI_FAMILY of socket_domain (*

强制使用指定的套接字域

*)
| AI_SOCKTYPE of socket_type (*

强制使用指定的套接字类型

*)
| AI_PROTOCOL of int (*

强制使用指定的协议

*)
| AI_NUMERICHOST (*

不调用名称解析器,期望数值型 IP 地址

*)
| AI_CANONNAME (*

填充结果的 ai_canonname 字段

*)
| AI_PASSIVE (*

将地址设置为“任意”地址,用于 Unix.bind

*)

传递给 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_PASSIVEservice 可以是服务名或端口号的字符串表示形式。 service 可以为空字符串;在这种情况下,返回地址的端口字段将设置为 0。 opts 是一个可能为空的选项列表,允许调用方强制使用特定的套接字域(例如,仅 IPv6 或仅 IPv4)或特定的套接字类型(例如,仅 TCP 或仅 UDP)。

type name_info = {
   ni_hostname : string; (*

主机名或 IP 地址

*)
   ni_service : string; (*

服务名或端口号

*)
}

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 是一个可能为空的选项列表,用于控制如何获取这些名称。

终端接口

以下函数实现了 POSIX 标准终端接口。它们提供了对异步通信端口和伪终端的控制。有关完整说明,请参阅 termios 手册页。

type terminal_io = {
   mutable c_ignbrk : bool; (*

忽略中断条件。

*)
   mutable c_brkint : bool; (*

在中断条件下发送中断信号。

*)
   mutable c_ignpar : bool; (*

忽略奇偶校验错误的字符。

*)
   mutable c_parmrk : bool; (*

标记奇偶校验错误。

*)
   mutable c_inpck : bool; (*

启用输入的奇偶校验检查。

*)
   mutable c_istrip : bool; (*

剥离输入字符的第 8 位。

*)
   mutable c_inlcr : bool; (*

将 NL 映射到输入的 CR。

*)
   mutable c_igncr : bool; (*

忽略输入的 CR。

*)
   mutable c_icrnl : bool; (*

将 CR 映射到输入的 NL。

*)
   mutable c_ixon : bool; (*

识别输入的 XON/XOFF 字符。

*)
   mutable c_ixoff : bool; (*

发出 XON/XOFF 字符以控制输入流。

*)
   mutable c_opost : bool; (*

启用输出处理。

*)
   mutable c_obaud : int; (*

输出波特率(0 表示关闭连接)。

*)
   mutable c_ibaud : int; (*

输入波特率。

*)
   mutable c_csize : int; (*

每个字符的位数(5-8)。

*)
   mutable c_cstopb : int; (*

停止位的数量(1-2)。

*)
   mutable c_cread : bool; (*

接收已启用。

*)
   mutable c_parenb : bool; (*

启用奇偶校验生成和检测。

*)
   mutable c_parodd : bool; (*

指定奇校验而不是偶校验。

*)
   mutable c_hupcl : bool; (*

在最后一次关闭时挂断。

*)
   mutable c_clocal : bool; (*

忽略调制解调器状态行。

*)
   mutable c_isig : bool; (*

在 INTR、QUIT、SUSP 上生成信号。

*)
   mutable c_icanon : bool; (*

启用规范处理(行缓冲和编辑)

*)
   mutable c_noflsh : bool; (*

禁用在 INTR、QUIT、SUSP 之后刷新。

*)
   mutable c_echo : bool; (*

回显输入字符。

*)
   mutable c_echoe : bool; (*

回显 ERASE(以擦除前一个字符)。

*)
   mutable c_echok : bool; (*

回显 KILL(以擦除当前行)。

*)
   mutable c_echonl : bool; (*

即使未设置 c_echo 也回显 NL。

*)
   mutable c_vintr : char; (*

中断字符(通常为 ctrl-C)。

*)
   mutable c_vquit : char; (*

退出字符(通常为 ctrl-\)。

*)
   mutable c_verase : char; (*

擦除字符(通常为 DEL 或 ctrl-H)。

*)
   mutable c_vkill : char; (*

删除行字符(通常为 ctrl-U)。

*)
   mutable c_veof : char; (*

文件结束字符(通常为 ctrl-D)。

*)
   mutable c_veol : char; (*

备用换行符。(通常为无)。

*)
   mutable c_vmin : int; (*

在读取请求满足之前要读取的最小字符数。

*)
   mutable c_vtime : int; (*

最大读取等待时间(以 0.1 秒为单位)。

*)
   mutable c_vstart : char; (*

启动字符(通常为 ctrl-Q)。

*)
   mutable c_vstop : char; (*

停止字符(通常为 ctrl-S)。

*)
}
val tcgetattr : file_descr -> terminal_io

返回由给定文件描述符引用的终端的状态。

type setattr_when = 
| TCSANOW
| TCSADRAIN
| TCSAFLUSH
val tcsetattr : file_descr -> setattr_when -> terminal_io -> unit

设置由给定文件描述符引用的终端的状态。第二个参数指示状态更改何时发生:立即(TCSANOW)、所有挂起的输出都已传输后(TCSADRAIN),或者在刷新所有已接收但尚未读取的输入后(TCSAFLUSH)。在更改输出参数时建议使用 TCSADRAIN;在更改输入参数时建议使用 TCSAFLUSH

val tcsendbreak : file_descr -> int -> unit

在给定文件描述符上发送中断条件。第二个参数是中断的持续时间,以 0.1 秒为单位;0 表示标准持续时间(0.25 秒)。

val tcdrain : file_descr -> unit

等待直到写入给定文件描述符的所有输出都已传输。

type flush_queue = 
| TCIFLUSH
| TCOFLUSH
| TCIOFLUSH
val tcflush : file_descr -> flush_queue -> unit

丢弃写入给定文件描述符但尚未传输的数据,或接收但尚未读取的数据,具体取决于第二个参数:TCIFLUSH 刷新接收但尚未读取的数据,TCOFLUSH 刷新写入但尚未传输的数据,TCIOFLUSH 刷新两者。

type flow_action = 
| TCOOFF
| TCOON
| TCIOFF
| TCION
val tcflow : file_descr -> flow_action -> unit

暂停或重新启动给定文件描述符上的数据接收或传输,具体取决于第二个参数:TCOOFF 暂停输出,TCOON 重新启动输出,TCIOFF 传输 STOP 字符以暂停输入,TCION 传输 START 字符以重新启动输入。

val setsid : unit -> int

将调用进程置于新的会话中,并将其与其控制终端分离。