模組 UnixLabels

module UnixLabels: sig .. end

與 Unix 系統的介面。

要使用此模組的標籤版本,請在您的實作中加入 module Unix = UnixLabels

注意:此模組的所有函數(除了 UnixLabels.error_messageUnixLabels.handle_unix_error)在底層系統呼叫發出錯誤訊號時,都有可能引發 UnixLabels.Unix_error 例外。


錯誤報告

type error = Unix.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 並傳回結果。如果引發 UnixLabels.Unix_error 例外,它會印出描述錯誤的訊息,並以程式碼 2 結束。

存取程序環境

val environment : unit -> string array

以 ``variable=value'' 格式的字串陣列傳回程序環境。如果程序具有特殊權限,則傳回的陣列為空。

val unsafe_environment : unit -> string array

以 ``variable=value'' 格式的字串陣列傳回程序環境。與 UnixLabels.environment 不同,即使程序具有特殊權限,此函數也會傳回已填入的陣列。請參閱 UnixLabels.unsafe_getenv 的文件以取得更多詳細資訊。

val getenv : string -> string

傳回程序環境中與變數相關聯的值,除非程序具有特殊權限。

val unsafe_getenv : string -> string

傳回程序環境中與變數相關聯的值。

UnixLabels.getenv 不同,即使程序具有特殊權限,此函數也會傳回值。它被認為是不安全的,因為 setuid 或 setgid 程式的程式設計師必須小心避免在可執行檔的搜尋路徑、臨時檔案或記錄檔的位置等中使用惡意製作的環境變數。

val putenv : string -> string -> unit

putenv name value 設定程序環境中與變數相關聯的值。name 是環境變數的名稱,而 value 是其新的相關聯值。

程序處理

type process_status = Unix.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-1073741819,所以 WEXITED -1073741819 是 Windows 中 WSIGNALED Sys.sigsegv 的對等物。

type wait_flag = Unix.wait_flag = 
| WNOHANG (*

如果沒有子程序死亡,則不要封鎖,而是立即傳回一個等於 0 的 pid。

*)
| WUNTRACED (*

也報告收到停止訊號的子程序。

*)

UnixLabels.waitpid 的旗標。

val execv : prog:string -> args:string array -> 'a

execv prog args 使用引數 args 和目前的程序環境,執行檔案 prog 中的程式。請注意,第一個引數 args.(0) 按照慣例是正在執行的程式的檔案名稱,就像 Sys.argv.(0) 一樣。這些 execv* 函數永遠不會傳回:成功時,目前的程式會被新的程式取代。

在 Windows 上:CRT 只是產生一個新的程序並結束目前的程序。如果例如另一個程序正在等待目前的程序,這會產生不必要的後果。建議改用 UnixLabels.create_process 或其中一個 open_process_* 函數。

val execve : prog:string -> args:string array -> env:string array -> 'a

UnixLabels.execv 相同,不同之處在於第三個引數提供要執行的程式的環境。

val execvp : prog:string -> args:string array -> 'a

UnixLabels.execv 相同,不同之處在於會在路徑中搜尋程式。

val execvpe : prog:string -> args:string array -> env:string array -> 'a

UnixLabels.execve 相同,差別在於程式會在路徑中搜尋。

val fork : unit -> int

建立新的行程 (process)。對於子行程,回傳的整數值為 0;對於父行程,回傳的值為子行程的 pid。如果 OCaml 行程是多核心的(已產生任何網域),則會失敗。此外,如果已產生來自 Thread 模組的任何執行緒,則子行程可能會處於損毀的狀態。

val wait : unit -> int * process_status

等待其中一個子行程終止,並回傳其 pid 和終止狀態。

val waitpid : mode:wait_flag list -> int -> int * process_status

UnixLabels.wait 相同,但會等待指定 pid 的子行程。pid 為 -1 表示等待任何子行程。pid 為 0 表示等待與目前行程在同一個行程群組中的任何子行程。負數的 pid 參數代表行程群組。選項列表指示 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._exit 的典型用途是在 Unix.fork 操作之後,當子行程遇到致命錯誤且必須結束時。在這種情況下,最好不要在子行程中執行任何最終化操作,因為這些操作可能會干擾父行程執行的類似操作。例如,子行程不應刷新輸出通道,因為父行程稍後可能會再次刷新它們,從而導致重複輸出。

val getpid : unit -> int

回傳行程的 pid。

val getppid : unit -> int

回傳父行程的 pid。

val nice : int -> int

變更行程優先權。整數參數會加到「nice」值。(「nice」值越高表示優先權越低。)回傳新的 nice 值。

基本檔案輸入/輸出

type file_descr = Unix.file_descr 

檔案描述子的抽象類型。

val stdin : file_descr

標準輸入的檔案描述子。

val stdout : file_descr

標準輸出的檔案描述子。

val stderr : file_descr

標準錯誤的檔案描述子。

type open_flag = Unix.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 (*

UnixLabels.openfile 回傳的描述子設定 close-on-exec 旗標。如需更多資訊,請參閱 UnixLabels.set_close_on_exec

*)
| O_KEEPEXEC (*

清除 close-on-exec 旗標。這目前是預設值。

*)

用於 UnixLabels.openfile 的旗標。

type file_perm = int 

檔案存取權的類型,例如 0o640 表示使用者讀寫,群組讀取,其他使用者無權限

val openfile : string ->
mode:open_flag list ->
perm:file_perm -> file_descr

以指定的旗標開啟具名檔案。第三個參數是如果建立檔案要給予的權限(請參閱 UnixLabels.umask)。回傳具名檔案的檔案描述子。

val close : file_descr -> unit

關閉檔案描述子。

val fsync : file_descr -> unit

將檔案緩衝區刷新到磁碟。

val read : file_descr -> buf:bytes -> pos:int -> len:int -> int

read fd ~buf ~pos ~len 從描述子 fd 讀取 len 個位元組,並將它們儲存在位元組序列 buf 中,從 buf 中的位置 pos 開始。回傳實際讀取的位元組數。

val read_bigarray : file_descr ->
buf:('a, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
Bigarray.Array1.t ->
pos:int -> len:int -> int

UnixLabels.read 相同,但將資料讀取到 bigarray 中。

val write : file_descr -> buf:bytes -> pos:int -> len:int -> int

write fd ~buf ~pos ~lenlen 個位元組寫入描述子 fd,並從位元組序列 buf 中取得,從 buff 中的位置 pos 開始。回傳實際寫入的位元組數。write 會重複寫入操作,直到所有位元組都已寫入或發生錯誤為止。

val write_bigarray : file_descr ->
buf:('a, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
Bigarray.Array1.t ->
pos:int -> len:int -> int

UnixLabels.write 相同,但從 bigarray 中取得資料。

val single_write : file_descr -> buf:bytes -> pos:int -> len:int -> int

UnixLabels.write 相同,但嘗試只寫入一次。因此,如果發生錯誤,single_write 保證沒有任何資料被寫入。

val write_substring : file_descr -> buf:string -> pos:int -> len:int -> int

UnixLabels.write 相同,但從字串而不是位元組序列中取得資料。

val single_write_substring : file_descr -> buf:string -> pos:int -> len:int -> int

UnixLabels.single_write 相同,但從字串而不是位元組序列中取得資料。

val single_write_bigarray : file_descr ->
buf:('a, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
Bigarray.Array1.t ->
pos:int -> len:int -> int

UnixLabels.single_write 相同,但從 bigarray 中取得資料。

與標準輸入/輸出函式庫介接

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 = Unix.seek_command = 
| SEEK_SET (*

表示相對於檔案開頭的位置

*)
| SEEK_CUR (*

表示相對於目前位置的位置

*)
| SEEK_END (*

表示相對於檔案結尾的位置

*)

UnixLabels.lseek 的定位模式。

val lseek : file_descr -> int -> mode:seek_command -> int

設定檔案描述子的目前位置,並回傳產生的位移量(從檔案開頭)。

val truncate : string -> len:int -> unit

將具名檔案截斷為指定的大小。

val ftruncate : file_descr -> len:int -> unit

將與指定描述子對應的檔案截斷為指定的大小。

檔案狀態

type file_kind = Unix.file_kind = 
| S_REG (*

一般檔案

*)
| S_DIR (*

目錄

*)
| S_CHR (*

字元裝置

*)
| S_BLK (*

區塊裝置

*)
| S_LNK (*

符號連結

*)
| S_FIFO (*

具名管道

*)
| S_SOCK (*

通訊端

*)
type stats = Unix.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; (*

上次狀態變更時間

*)
}

UnixLabels.stat 呼叫所傳回的資訊。

val stat : string -> stats

傳回指定名稱檔案的資訊。

val lstat : string -> stats

UnixLabels.stat 相同,但如果檔案是符號連結,則傳回連結本身的資訊。

val fstat : file_descr -> stats

傳回與給定描述符相關聯的檔案資訊。

val isatty : file_descr -> bool

如果給定的檔案描述符指的是終端機或主控台視窗,則傳回 true,否則傳回 false

大型檔案的檔案操作

module LargeFile: sig .. end

大型檔案的檔案操作。

將檔案映射到記憶體

val map_file : file_descr ->
?pos:int64 ->
kind:('a, 'b) Bigarray.kind ->
layout:'c Bigarray.layout ->
shared:bool -> dims:int array -> ('a, 'b, 'c) Bigarray.Genarray.t

將檔案以 Bigarray 的形式進行記憶體映射。map_file fd ~kind ~layout ~shared ~dims 會傳回一個種類為 kind、版面配置為 layout,且維度如 dims 中指定的 Bigarray。此 Bigarray 中包含的資料是檔案描述符 fd 所參照檔案的內容 (例如,先前使用 UnixLabels.openfile 開啟)。可選的 pos 參數是檔案中被映射資料的位元組偏移量;其預設值為 0 (從檔案開頭開始映射)。

如果 sharedtrue,則對陣列執行的所有修改都會反映在檔案中。這需要以寫入權限開啟 fd。如果 sharedfalse,則對陣列執行的修改僅在記憶體中進行,並使用修改頁面的複製寫入;底層檔案不會受到影響。

UnixLabels.map_file 比起將整個檔案讀入 Bigarray、修改該 Bigarray,然後再寫入更有效率。

若要根據檔案的實際大小自動調整 Bigarray 的維度,則主要維度 (也就是說,對於 C 版面配置的陣列是第一個維度,對於 Fortran 版面配置的陣列是最後一個維度) 可以指定為 -1UnixLabels.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 : src:string -> dst:string -> unit

rename ~src ~dst 會將檔案名稱從 src 變更為 dst,並視需要將其在目錄之間移動。如果 dst 已經存在,則其內容將被 src 的內容取代。根據作業系統的不同,dst 的中繼資料 (權限、擁有者等) 可以保留或被 src 的中繼資料取代。

val link : ?follow:bool -> src:string -> dst: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 = Unix.access_permission = 
| R_OK (*

讀取權限

*)
| W_OK (*

寫入權限

*)
| X_OK (*

執行權限

*)
| F_OK (*

檔案已存在

*)

用於 UnixLabels.access 呼叫的旗標。

val chmod : string -> perm:file_perm -> unit

變更指定名稱檔案的權限。

val fchmod : file_descr -> perm:file_perm -> unit

變更已開啟檔案的權限。

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

變更指定名稱檔案的擁有者 uid 和擁有者 gid。

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

變更已開啟檔案的擁有者 uid 和擁有者 gid。

val umask : file_perm -> file_perm

設定程序的檔案模式建立遮罩,並傳回先前的遮罩。

val access : string -> perm:access_permission list -> unit

檢查程序是否具有指定名稱檔案的給定權限。

在 Windows 上:無法測試執行權限 X_OK,僅改為測試讀取權限。

檔案描述符的操作

val dup : ?cloexec:bool -> file_descr -> file_descr

傳回一個新的檔案描述符,該描述符參照與給定描述符相同的檔案。請參閱 UnixLabels.set_close_on_exec,以取得關於 cloexec 可選引數的文件。

val dup2 : ?cloexec:bool ->
src:file_descr -> dst:file_descr -> unit

dup2 ~src ~dstsrc 複製到 dst,如果 dst 已開啟,則關閉 dst。請參閱 UnixLabels.set_close_on_exec,以取得關於 cloexec 可選引數的文件。

val set_nonblock : file_descr -> unit

在給定的描述符上設定「非封鎖」旗標。當設定非封鎖旗標時,讀取一個暫時沒有可用資料的描述符會引發 EAGAINEWOULDBLOCK 錯誤,而不是封鎖;寫入一個暫時沒有寫入空間的描述符也會引發 EAGAINEWOULDBLOCK

val clear_nonblock : file_descr -> unit

清除給定描述符上的「非封鎖」旗標。請參閱 UnixLabels.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

清除指定描述子的「執行時關閉 (close-on-exec)」旗標。請參閱 UnixLabels.set_close_on_exec

目錄

val mkdir : string -> perm:file_perm -> unit

使用給定的權限建立目錄(請參閱 UnixLabels.umask)。

val rmdir : string -> unit

移除空的目錄。

val chdir : string -> unit

變更程序的工作目錄。

val getcwd : unit -> string

傳回目前工作目錄的名稱。

val chroot : string -> unit

變更程序的根目錄。

type dir_handle = Unix.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 選用參數的文件,請參閱 UnixLabels.set_close_on_exec

val mkfifo : string -> perm:file_perm -> unit

使用給定的權限建立具名管道(請參閱 UnixLabels.umask)。

高階程序與重導向管理

val create_process : prog:string ->
args:string array ->
stdin:file_descr ->
stdout:file_descr -> stderr:file_descr -> int

create_process ~prog ~args ~stdin ~stdout ~stderr 會建立一個新的程序,該程序使用引數 args 執行檔案 prog 中的程式。請注意,按照慣例,第一個引數 args.(0) 是正在執行的程式的檔案名稱,就像 Sys.argv.(0) 一樣。新程序的 PID 會立即傳回;新程序會與目前程序並行執行。新程序的標準輸入和輸出會連接到描述子 stdinstdoutstderr。例如,為 stdout 傳遞 Unix.stdout 可以防止重新導向,並使新程序擁有與目前程序相同的標準輸出。可執行檔案 prog 會在路徑中搜尋。新程序擁有與目前程序相同的環境。

val create_process_env : prog:string ->
args:string array ->
env:string array ->
stdin:file_descr ->
stdout:file_descr -> stderr:file_descr -> int

create_process_env ~prog ~args ~env ~stdin ~stdout ~stderr 的運作方式與 UnixLabels.create_process 相同,差別在於額外的引數 env 指定傳遞給程式的環境。

val open_process_in : string -> in_channel

高階管道和程序管理。此函式會與程式平行執行給定的命令。該命令的標準輸出會重新導向至管道,該管道可以透過傳回的輸入通道讀取。該命令會由 shell /bin/sh 解譯(在 Windows 上則是 cmd.exe),請參閱 UnixLabels.systemFilename.quote_command 函式可用於為正在使用的 shell 適當引用命令及其引數。如果命令不需要透過 shell 執行,則可以使用 UnixLabels.open_process_args_in,以更穩健且更有效率的方式替代 UnixLabels.open_process_in

val open_process_out : string -> out_channel

UnixLabels.open_process_in 相同,但會將命令的標準輸入重新導向至管道。寫入傳回的輸出通道的資料會傳送至命令的標準輸入。警告:輸出通道上的寫入會被緩衝,因此請注意在正確的時間呼叫 flush,以確保正確的同步。如果命令不需要透過 shell 執行,則可以使用 UnixLabels.open_process_args_out 來取代 UnixLabels.open_process_out

val open_process : string -> in_channel * out_channel

UnixLabels.open_process_out 相同,但會將命令的標準輸入和標準輸出都重新導向至連接到兩個傳回通道的管道。輸入通道會連接到命令的輸出,而輸出通道會連接到命令的輸入。如果命令不需要透過 shell 執行,則可以使用 UnixLabels.open_process_args 來取代 UnixLabels.open_process

val open_process_full : string ->
env:string array ->
in_channel * out_channel * in_channel

UnixLabels.open_process 類似,但第二個引數指定傳遞給命令的環境。結果會是三個通道的 tuple,分別連接到命令的標準輸出、標準輸入和標準錯誤。如果命令不需要透過 shell 執行,則可以使用 UnixLabels.open_process_args_full 來取代 UnixLabels.open_process_full

val open_process_args : string -> string array -> in_channel * out_channel

open_process_args prog args 會使用引數 args 執行程式 prog。請注意,按照慣例,第一個引數 args.(0) 是正在執行的程式的檔案名稱,就像 Sys.argv.(0) 一樣。新程序會與目前程序並行執行。新程序的標準輸入和輸出會重新導向至管道,這些管道可以分別透過傳回的通道讀取和寫入。輸入通道會連接到程式的輸出,而輸出通道會連接到程式的輸入。

警告:輸出通道上的寫入會被緩衝,因此請注意在正確的時間呼叫 flush,以確保正確的同步。

可執行檔案 prog 會在路徑中搜尋。此行為在 4.12 中已變更;先前 prog 僅在目前目錄中查找。

新程序擁有與目前程序相同的環境。

val open_process_args_in : string -> string array -> in_channel

UnixLabels.open_process_args 相同,但只會重新導向新程序的標準輸出。

val open_process_args_out : string -> string array -> out_channel

UnixLabels.open_process_args 相同,但只會重新導向新程序的標準輸入。

val open_process_args_full : string ->
string array ->
string array -> in_channel * out_channel * in_channel

UnixLabels.open_process_args 類似,但第三個引數會指定傳遞給新程序的環境。結果會是三個通道的 tuple,分別連接到程式的標準輸出、標準輸入和標準錯誤。

val process_in_pid : in_channel -> int

傳回透過 UnixLabels.open_process_args_in 開啟的程序 PID,或透過 UnixLabels.open_process_in 開啟的 shell 的 PID。

val process_out_pid : out_channel -> int

傳回透過 UnixLabels.open_process_args_out 開啟的程序 PID,或透過 UnixLabels.open_process_out 開啟的 shell 的 PID。

val process_pid : in_channel * out_channel -> int

傳回透過 UnixLabels.open_process_args 開啟的程序 PID,或透過 UnixLabels.open_process_args 開啟的 shell 的 PID。

val process_full_pid : in_channel * out_channel * in_channel -> int

傳回透過 UnixLabels.open_process_args_full 開啟的程序 PID,或透過 UnixLabels.open_process_full 開啟的 shell 的 PID。

val close_process_in : in_channel -> process_status

關閉由 UnixLabels.open_process_in 開啟的通道,等待相關的命令終止,並傳回其終止狀態。

val close_process_out : out_channel -> process_status

關閉由 UnixLabels.open_process_out 開啟的通道,等待相關的命令終止,並傳回其終止狀態。

val close_process : in_channel * out_channel -> process_status

關閉由 UnixLabels.open_process 開啟的通道,等待相關的命令終止,並傳回其終止狀態。

val close_process_full : in_channel * out_channel * in_channel ->
process_status

關閉由 UnixLabels.open_process_full 開啟的通道,等待相關的命令終止,並傳回其終止狀態。

val symlink : ?to_dir:bool -> src:string -> dst: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。

可以使用 UnixLabels.has_symlink 來檢查程序是否能夠建立符號連結。

val has_symlink : unit -> bool

如果使用者能夠建立符號連結,則傳回 true。在 Windows 上,這表示使用者不僅具有 SeCreateSymbolicLinkPrivilege,而且還以提升的權限執行(如果需要)。在其他平台上,這僅表示 symlink 系統呼叫可用。

val readlink : string -> string

讀取符號連結的內容。

輪詢

val select : read:file_descr list ->
write:file_descr list ->
except:file_descr list ->
timeout:float ->
file_descr list * file_descr list *
file_descr list

等待某些通道上的輸入/輸出操作成為可能。三個列表參數分別是要檢查讀取(第一個參數)、寫入(第二個參數)或異常情況(第三個參數)的描述符集合。第四個參數是最大逾時時間(以秒為單位);負值的第四個參數表示沒有逾時(無限等待)。結果由三組描述符組成:準備好讀取的描述符(第一個元件)、準備好寫入的描述符(第二個元件)以及正在等待異常情況的描述符(第三個元件)。

鎖定

type lock_command = Unix.lock_command = 
| F_ULOCK (*

解鎖一個區域

*)
| F_LOCK (*

鎖定一個區域進行寫入,如果已被鎖定則會阻擋

*)
| F_TLOCK (*

鎖定一個區域進行寫入,如果已被鎖定則會失敗

*)
| F_TEST (*

測試一個區域是否被其他進程鎖定

*)
| F_RLOCK (*

鎖定一個區域進行讀取,如果已被鎖定則會阻擋

*)
| F_TRLOCK (*

鎖定一個區域進行讀取,如果已被鎖定則會失敗

*)

UnixLabels.lockf 的命令。

val lockf : file_descr -> mode:lock_command -> len:int -> unit

lockf fd ~mode ~len 在以 fd 開啟的檔案的某個區域上放置鎖定。該區域從 fd 的當前讀/寫位置開始(由 UnixLabels.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 : pid:int -> signal:int -> unit

kill ~pid ~signal 將訊號編號 signal 送至 id 為 pid 的進程。

在 Windows 上:僅模擬 Sys.sigkill 訊號。

type sigprocmask_command = Unix.sigprocmask_command = 
| SIG_SETMASK
| SIG_BLOCK
| SIG_UNBLOCK
val sigprocmask : mode: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 = Unix.process_times = {
   tms_utime : float; (*

進程的使用者時間

*)
   tms_stime : float; (*

進程的系統時間

*)
   tms_cutime : float; (*

子進程的使用者時間

*)
   tms_cstime : float; (*

子進程的系統時間

*)
}

進程的執行時間(CPU 時間)。

type tm = Unix.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

UnixLabels.time 相同,但解析度優於 1 秒。

val gmtime : float -> tm

UnixLabels.time 傳回的秒數時間轉換為日期和時間。假設為 UTC(協調世界時),也稱為 GMT。若要執行反向轉換,請將 TZ 環境變數設定為 "UTC",使用 UnixLabels.mktime,然後還原 TZ 的原始值。

val localtime : float -> tm

UnixLabels.time 傳回的秒數時間轉換為日期和時間。假設為本地時區。執行反向轉換的函數為 UnixLabels.mktime

val mktime : tm -> float * tm

將由 tm 參數指定的日期和時間轉換為 UnixLabels.time 傳回的秒數時間。tmtm_isdsttm_wdaytm_yday 欄位會被忽略。也傳回給定 tm 記錄的正規化複本,其中 tm_wdaytm_ydaytm_isdst 欄位會從其他欄位重新計算,而其他欄位會正規化(例如,40 月 10 日會變更為 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 -> access:float -> modif:float -> unit

設定檔案的上次存取時間(第二個參數)和上次修改時間(第三個參數)。時間以自 1970 年 1 月 1 日 00:00:00 GMT 以來的秒數表示。如果兩個時間都是 0.0,則存取時間和上次修改時間都會設定為目前時間。

type interval_timer = Unix.interval_timer = 
| ITIMER_REAL (*

以實際時間遞減,並在過期時傳送訊號 SIGALRM

*)
| ITIMER_VIRTUAL (*

在進程虛擬時間內遞減,並在過期時傳送 SIGVTALRM

*)
| ITIMER_PROF (*

(用於分析)當進程執行時以及系統代表進程執行時都會遞減;它會在過期時傳送 SIGPROF

*)

三種類型的間隔計時器。

type interval_timer_status = Unix.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 = Unix.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 = Unix.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 = Unix.inet_addr 

網際網路位址的抽象類型。

val inet_addr_of_string : string -> inet_addr

將網際網路位址的可列印表示法轉換為其內部表示法。引數字串對於 IPv4 位址由 4 個以句點分隔的數字 (XXX.YYY.ZZZ.TTT) 組成,對於 IPv6 位址則由最多 8 個以冒號分隔的數字組成。

val string_of_inet_addr : inet_addr -> string

傳回給定網際網路位址的可列印表示法。關於可列印表示法的描述,請參閱 UnixLabels.inet_addr_of_string

val inet_addr_any : inet_addr

一個特殊的 IPv4 位址,僅用於 bind,表示主機擁有的所有網際網路位址。

val inet_addr_loopback : inet_addr

一個特殊的 IPv4 位址,表示主機 (127.0.0.1)。

val inet6_addr_any : inet_addr

一個特殊的 IPv6 位址,僅用於 bind,表示主機擁有的所有網際網路位址。

val inet6_addr_loopback : inet_addr

一個特殊的 IPv6 位址,表示主機 (::1)。

val is_inet6_addr : inet_addr -> bool

判斷給定的 inet_addr 是否為 IPv6 位址。

套接字

type socket_domain = Unix.socket_domain = 
| PF_UNIX (*

Unix 網域

*)
| PF_INET (*

網際網路網域 (IPv4)

*)
| PF_INET6 (*

網際網路網域 (IPv6)

*)

socket 網域的類型。並非所有平台都支援 IPv6 socket (類型 PF_INET6)。

在 Windows 上:Windows 10 1803 及更新版本中,自 4.14.0 起支援 PF_UNIX

type socket_type = Unix.socket_type = 
| SOCK_STREAM (*

串流 socket

*)
| SOCK_DGRAM (*

資料包 socket

*)
| SOCK_RAW (*

原始 socket

*)
| SOCK_SEQPACKET (*

循序封包 socket

*)

socket 種類的類型,指定通訊的語意。SOCK_SEQPACKET 為了完整性而包含在內,但很少受作業系統支援,並且需要此程式庫中無法使用的系統呼叫。

type sockaddr = Unix.sockaddr = 
| ADDR_UNIX of string
| ADDR_INET of inet_addr * int

socket 位址的類型。ADDR_UNIX name 是 Unix 網域中的 socket 位址;name 是檔案系統中的檔案名稱。ADDR_INET(addr,port) 是網際網路網域中的 socket 位址;addr 是機器的網際網路位址,而 port 是連接埠號碼。

val socket : ?cloexec:bool ->
domain:socket_domain ->
kind:socket_type -> protocol:int -> file_descr

在給定的網域中,使用給定的種類建立一個新的 socket。第三個引數是協定類型;0 會選擇該種類 socket 的預設協定。關於 cloexec 選用引數的說明文件,請參閱 UnixLabels.set_close_on_exec

val domain_of_sockaddr : sockaddr -> socket_domain

傳回適用於給定 socket 位址的 socket 網域。

val socketpair : ?cloexec:bool ->
domain:socket_domain ->
kind:socket_type ->
protocol:int -> file_descr * file_descr

建立一對連線在一起的未命名 socket。關於 cloexec 選用引數的說明文件,請參閱 UnixLabels.set_close_on_exec

val accept : ?cloexec:bool ->
file_descr -> file_descr * sockaddr

接受給定 socket 上的連線。傳回的描述符是連線到用戶端的 socket;傳回的位址是連線用戶端的位址。關於 cloexec 選用引數的說明文件,請參閱 UnixLabels.set_close_on_exec

val bind : file_descr -> addr:sockaddr -> unit

將 socket 繫結至位址。

val connect : file_descr -> addr:sockaddr -> unit

將 socket 連線至位址。

val listen : file_descr -> max:int -> unit

設定 socket 以接收連線要求。整數引數是最大待處理要求數。

type shutdown_command = Unix.shutdown_command = 
| SHUTDOWN_RECEIVE (*

關閉以進行接收

*)
| SHUTDOWN_SEND (*

關閉以進行傳送

*)
| SHUTDOWN_ALL (*

兩者都關閉

*)

shutdown 的命令類型。

val shutdown : file_descr -> mode:shutdown_command -> unit

關閉 socket 連線。第二個引數使用 SHUTDOWN_SEND 會導致連線另一端的讀取傳回檔案結尾條件。SHUTDOWN_RECEIVE 會導致連線另一端的寫入傳回關閉的管線條件 (SIGPIPE 信號)。

val getsockname : file_descr -> sockaddr

傳回給定 socket 的位址。

val getpeername : file_descr -> sockaddr

傳回連線至給定 socket 的主機位址。

type msg_flag = Unix.msg_flag = 
| MSG_OOB
| MSG_DONTROUTE
| MSG_PEEK
val recv : file_descr ->
buf:bytes -> pos:int -> len:int -> mode:msg_flag list -> int

從已連線的 socket 接收資料。

val recvfrom : file_descr ->
buf:bytes ->
pos:int ->
len:int -> mode:msg_flag list -> int * sockaddr

從未連線的 socket 接收資料。

val send : file_descr ->
buf:bytes -> pos:int -> len:int -> mode:msg_flag list -> int

透過已連線的 socket 傳送資料。

val send_substring : file_descr ->
buf:string -> pos:int -> len:int -> mode:msg_flag list -> int

send 相同,但從字串而非位元組序列取得資料。

val sendto : file_descr ->
buf:bytes ->
pos:int ->
len:int -> mode:msg_flag list -> addr:sockaddr -> int

透過未連線的 socket 傳送資料。

val sendto_substring : file_descr ->
buf:string ->
pos:int ->
len:int -> mode:msg_flag list -> sockaddr -> int

sendto 相同,但從字串而非位元組序列取得資料。

套接字選項

type socket_bool_option = Unix.socket_bool_option = 
| SO_DEBUG (*

記錄偵錯資訊

*)
| SO_BROADCAST (*

允許傳送廣播訊息

*)
| SO_REUSEADDR (*

允許重複使用本機位址以進行繫結

*)
| SO_KEEPALIVE (*

保持連線作用中

*)
| SO_DONTROUTE (*

略過標準路由演算法

*)
| SO_OOBINLINE (*

將頻外資料保留在行中

*)
| SO_ACCEPTCONN (*

報告是否已啟用 socket 接聽

*)
| TCP_NODELAY (*

控制 TCP socket 的 Nagle 演算法

*)
| IPV6_ONLY (*

禁止將 IPv6 socket 繫結至 IPv4 位址

*)
| SO_REUSEPORT (*

允許重複使用位址和連接埠繫結

*)

可以使用 UnixLabels.getsockopt 查詢,並使用 UnixLabels.setsockopt 修改的 socket 選項。這些選項具有布林值 (true/false)。

type socket_int_option = Unix.socket_int_option = 
| SO_SNDBUF (*

傳送緩衝區的大小

*)
| SO_RCVBUF (*

接收緩衝區的大小

*)
| SO_ERROR (*
已淘汰。請改用 Unix.getsockopt_error。

已淘汰。請改用 UnixLabels.getsockopt_error

*)
| SO_TYPE (*

報告 socket 類型

*)
| SO_RCVLOWAT (*

輸入操作要處理的最小位元組數

*)
| SO_SNDLOWAT (*

輸出操作要處理的最小位元組數

*)

可以使用 UnixLabels.getsockopt_int 查詢,並使用 UnixLabels.setsockopt_int 修改的 socket 選項。這些選項具有整數值。

type socket_optint_option = Unix.socket_optint_option = 
| SO_LINGER (*

是否在存在資料的情況下延遲關閉的連線,以及延遲多長時間(以秒為單位)

*)

可以使用 UnixLabels.getsockopt_optint 查詢,並使用 UnixLabels.setsockopt_optint 修改的 socket 選項。這些選項的值為 int option 類型,其中 None 表示「已停用」。

type socket_float_option = Unix.socket_float_option = 
| SO_RCVTIMEO (*

輸入操作的逾時

*)
| SO_SNDTIMEO (*

輸出操作的逾時

*)

可以使用 UnixLabels.getsockopt_float 查詢,並使用 UnixLabels.setsockopt_float 修改的 socket 選項。這些選項具有浮點數值,表示以秒為單位的時間。值 0 表示無限逾時。

val getsockopt : file_descr -> socket_bool_option -> bool

傳回給定 socket 中布林值選項的目前狀態。

val setsockopt : file_descr -> socket_bool_option -> bool -> unit

設定或清除給定 socket 中的布林值選項。

val getsockopt_int : file_descr -> socket_int_option -> int

UnixLabels.getsockopt 相同,用於整數值 socket 選項。

val setsockopt_int : file_descr -> socket_int_option -> int -> unit

UnixLabels.setsockopt 相同,用於整數值 socket 選項。

val getsockopt_optint : file_descr -> socket_optint_option -> int option

UnixLabels.getsockopt 相同,用於其值為 int option 的 socket 選項。

val setsockopt_optint : file_descr ->
socket_optint_option -> int option -> unit

UnixLabels.setsockopt 相同,用於其值為 int option 的 socket 選項。

val getsockopt_float : file_descr -> socket_float_option -> float

UnixLabels.getsockopt 相同,用於其值為浮點數的 socket 選項。

val setsockopt_float : file_descr -> socket_float_option -> float -> unit

UnixLabels.setsockopt 相同,用於其值為浮點數的 socket 選項。

val getsockopt_error : file_descr -> error option

傳回與給定 socket 相關聯的錯誤條件,並清除它。

高階網路連線函數

val open_connection : sockaddr -> in_channel * out_channel

連線到給定位址的伺服器。傳回一對連線到伺服器的緩衝通道。請記得在適當的時間在輸出通道上呼叫 flush,以確保正確的同步處理。

open_connection 傳回的兩個通道會共用一個 socket 的描述符。因此,當連線結束時,您應該在輸出通道上呼叫 close_out,這也會關閉底層的 socket。請勿在輸入通道上呼叫 close_in;它最終會由 GC 收集。

val shutdown_connection : in_channel -> unit

「關閉」使用 UnixLabels.open_connection 建立的連線;也就是說,將檔案結尾條件傳輸到連線另一端進行讀取的伺服器。這不會關閉連線使用的 socket 和通道。關於如何在連線結束後關閉它們,請參閱 Unix.open_connection

val establish_server : (in_channel -> out_channel -> unit) ->
addr:sockaddr -> unit

在給定位址上建立伺服器。針對每個連線呼叫第一個引數中給定的函式,其中包含連線到用戶端的兩個緩衝通道。每個連線都會建立一個新的程序。UnixLabels.establish_server 函式永遠不會正常傳回。

提供給函式的兩個通道會共用一個 socket 的描述符。函式不需要關閉通道,因為當函式傳回時會自動發生。如果函式偏好明確關閉,則它應該使用 close_out 關閉輸出通道,並保持輸入通道未關閉,原因說明請參閱 Unix.in_channel_of_descr

主機與協定資料庫

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

hosts 資料庫中條目的結構。

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

protocols 資料庫中條目的結構。

type service_entry = Unix.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 -> protocol:string -> service_entry

services 中尋找具有指定名稱的條目。

val getservbyport : int -> protocol:string -> service_entry

services 中尋找具有指定服務編號的條目。

type addr_info = Unix.addr_info = {
   ai_family : socket_domain; (*

Socket 網域

*)
   ai_socktype : socket_type; (*

Socket 類型

*)
   ai_protocol : int; (*

Socket 協定編號

*)
   ai_addr : sockaddr; (*

位址

*)
   ai_canonname : string; (*

正規主機名稱

*)
}

UnixLabels.getaddrinfo 傳回的位址資訊。

type getaddrinfo_option = Unix.getaddrinfo_option = 
| AI_FAMILY of socket_domain (*

強制使用指定的 socket 網域

*)
| AI_SOCKTYPE of socket_type (*

強制使用指定的 socket 類型

*)
| AI_PROTOCOL of int (*

強制使用指定的協定

*)
| AI_NUMERICHOST (*

不呼叫名稱解析器,預期使用數值 IP 位址

*)
| AI_CANONNAME (*

填入結果的 ai_canonname 欄位

*)
| AI_PASSIVE (*

將位址設定為「任何」位址,以用於 UnixLabels.bind

*)

用於 UnixLabels.getaddrinfo 的選項。

val getaddrinfo : string ->
string -> getaddrinfo_option list -> addr_info list

getaddrinfo host service opts 會傳回 UnixLabels.addr_info 記錄的列表,其中描述適用於與指定主機和服務通訊的 socket 參數和位址。如果主機或服務名稱未知,或無法滿足 opts 中表達的限制,則會傳回空列表。

host 是主機名稱或 IP 位址的字串表示形式。host 可以指定為空字串;在這種情況下,會使用「任何」位址或「迴路」位址,具體取決於 opts 是否包含 AI_PASSIVEservice 是服務名稱或連接埠號碼的字串表示形式。service 可以指定為空字串;在這種情況下,傳回的位址的連接埠欄位會設定為 0。opts 是一個可能為空的選項列表,允許呼叫者強制使用特定的 socket 網域(例如僅限 IPv6 或僅限 IPv4)或特定的 socket 類型(例如僅限 TCP 或僅限 UDP)。

type name_info = Unix.name_info = {
   ni_hostname : string; (*

主機名稱或 IP 位址

*)
   ni_service : string; (*

服務名稱或連接埠號碼

*)
}

UnixLabels.getnameinfo 傳回的主機和服務資訊。

type getnameinfo_option = Unix.getnameinfo_option = 
| NI_NOFQDN (*

不限定本機主機名稱

*)
| NI_NUMERICHOST (*

一律以 IP 位址形式傳回主機

*)
| NI_NAMEREQD (*

如果無法判斷主機名稱,則失敗

*)
| NI_NUMERICSERV (*

一律以連接埠號碼形式傳回服務

*)
| NI_DGRAM (*

將服務視為以 UDP 為基礎,而不是預設的 TCP

*)

用於 UnixLabels.getnameinfo 的選項。

val getnameinfo : sockaddr ->
getnameinfo_option list -> name_info

getnameinfo addr opts 會傳回與 socket 位址 addr 相對應的主機名稱和服務名稱。opts 是一個可能為空的選項列表,用於管理如何取得這些名稱。

終端機介面

以下函式實作 POSIX 標準終端機介面。它們提供對非同步通訊連接埠和虛擬終端機的控制。如需完整說明,請參閱 termios 手冊頁。

type terminal_io = Unix.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 = Unix.setattr_when = 
| TCSANOW
| TCSADRAIN
| TCSAFLUSH
val tcsetattr : file_descr ->
mode:setattr_when -> terminal_io -> unit

設定由指定檔案描述元參照的終端機狀態。第二個引數表示狀態變更發生的時間:立即 (TCSANOW)、在所有擱置的輸出傳輸完成後 (TCSADRAIN) 或在清除所有已接收但未讀取的輸入後 (TCSAFLUSH)。變更輸出參數時建議使用 TCSADRAIN;變更輸入參數時建議使用 TCSAFLUSH

val tcsendbreak : file_descr -> duration:int -> unit

在指定的檔案描述元上傳送中斷狀況。第二個引數是中斷的持續時間,單位為 0.1 秒;0 表示標準持續時間 (0.25 秒)。

val tcdrain : file_descr -> unit

等待直到在指定檔案描述元上寫入的所有輸出傳輸完成。

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

根據第二個引數,捨棄寫入在指定檔案描述元上但尚未傳輸的資料,或已接收但尚未讀取的資料:TCIFLUSH 清除已接收但未讀取的資料,TCOFLUSH 清除已寫入但尚未傳輸的資料,而 TCIOFLUSH 則同時清除兩者。

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

根據第二個參數,暫停或重新開始指定檔案描述符上的資料接收或傳輸:TCOOFF 暫停輸出,TCOON 重新開始輸出,TCIOFF 傳送一個 STOP 字元以暫停輸入,而 TCION 傳送一個 START 字元以重新開始輸入。

val setsid : unit -> int

將呼叫的程序放入新的會話中,並將其與控制終端分離。