在 Unix 和類 Unix 操作系統中,檔案描述符(FD)作為一種獨特的識別符,用來標識文件或其他輸入/輸出資源。它們使系統中的文件操作變得更加方便和靈活。
檔案描述符通常由一個非負整數值組成,負值則被保留用以指示「沒有值」或錯誤條件。
每個 Unix 過程至少會有三個標準的 POSIX 檔案描述符,分別對應於三個標準流:標準輸入、標準輸出和標準錯誤。這種設計不僅影響了程序的性能,還影響了用戶的操作方式。
在傳統的 Unix 實現中,檔案描述符是指向一個由內核維護的每個過程的檔案描述符表的索引,這又索引到一個系統範圍的由所有過程開啟的文件表中。這個表記錄了文件的打開模式:讀取、寫入、附加,甚至可能有其他模式。
為了執行輸入或輸出,過程將檔案描述符通過系統調用傳遞給內核,內核將會代表過程訪問文件。
因此,過程並不直接訪問文件或 inode 表。在 Linux 系統中,過程打開的檔案描述符可以通過路徑 /proc/PID/fd/
訪問,其中 PID 是過程識別符。每個檔案描述符分別代表標準輸入(/proc/PID/fd/0
)、標準輸出(/proc/PID/fd/1
)和標準錯誤(/proc/PID/fd/2
)。
在 Unix 類系統中,檔案描述符可以指向文件系統中命名的任何 Unix 文件類型。這不僅包括常規文件,還包括目錄、塊設備和字符設備(也稱為「特殊文件」)、Unix 域套接字和命名管道。檔案描述符還可以參考其他通常不在文件系統中存在的對象,如匿名管道和網絡套接字。
在 C 標準 I/O 庫中,FILE 數據結構通常包括所涉及對象的低級檔案描述符。
這意味着複雜的抽象和底層操作已經被封裝進入了更加易於使用的接口中,這就是我們所說的檔案句柄。
以下是現代 Unix 類系統中針對檔案描述符的一些典型操作。大多數這些函數在 <unistd.h>
標頭中聲明,但某些則在 <fcntl.h>
標頭中。
開啟檔案描述符的幾種方式包括:
糾正或獲取檔案描述符的狀態的各類函數包括:
為了有效管理多個描述符,您可以使用:
這使得處理併發連接和事件成為可能。
例如:
Unix 系統還提供檔案鎖定和套接字操作的能力,包括:
檔案描述符在許多方面類似於能力。通過 Unix 域套接字進行的 sendmsg()
系統調用允許描述符在過程之間進行傳遞,這為資源的安全共享提供了潛力。
但是,這種能力的安全性受到潛在可變狀態的影響。
因為一旦程序共享同一檔案描述符的訪問,就可能會干擾彼此的使用,這使得使用檔案描述符作為能力變得複雜。
隨著 UNIX 系統不斷演化,許多新操作也在被標準化,以提供更好的保護和靈活性。
作為使用者,您是否曾經想過檔案描述符對於過程管理和數據流控制的真正影響是什麼呢?