Linux中的文件描述符
我們知道在Linux系統(tǒng)中一切皆可以看成是文件,文件又可分為:普通文件、目錄文件、鏈接文件和設(shè)備文件。在操作這些所謂的文件的時候,我們每操作一次就找一次名字,這會耗費大量的時間和效率。所以Linux中規(guī)定每一個文件對應(yīng)一個索引,這樣要操作文件的時候,我們直接找到索引就可以對其進行操作了。
文件描述符(file descriptor)就是內(nèi)核為了高效管理這些已經(jīng)被打開的文件所創(chuàng)建的索引,其是一個非負整數(shù)(通常是小整數(shù)),用于指代被打開的文件,所有執(zhí)行I/O操作的系統(tǒng)調(diào)用都通過文件描述符來實現(xiàn)。同時還規(guī)定系統(tǒng)剛剛啟動的時候,0是標(biāo)準(zhǔn)輸入,1是標(biāo)準(zhǔn)輸出,2是標(biāo)準(zhǔn)錯誤。這意味著如果此時去打開一個新的文件,它的文件描述符會是3,再打開一個文件文件描述符就是4......
Linux內(nèi)核對所有打開的文件有一個文件描述符表格,里面存儲了每個文件描述符作為索引與一個打開文件相對應(yīng)的關(guān)系,簡單理解就是下圖這樣一個數(shù)組,文件描述符(索引)就是文件描述符表這個數(shù)組的下標(biāo),數(shù)組的內(nèi)容就是指向一個個打開的文件的指針。
上面只是簡單理解,實際上關(guān)于文件描述符,Linux內(nèi)核維護了3個數(shù)據(jù)結(jié)構(gòu):
進程級的文件描述符表
系統(tǒng)級的打開文件描述符表
文件系統(tǒng)的i-node表
一個 Linux 進程啟動后,會在內(nèi)核空間中創(chuàng)建一個 PCB 控制塊,PCB 內(nèi)部有一個文件描述符表(File descriptor table),記錄著當(dāng)前進程所有可用的文件描述符,也即當(dāng)前進程所有打開的文件。進程級的描述符表的每一條記錄了單個進程所使用的文件描述符的相關(guān)信息,進程之間相互獨立,一個進程使用了文件描述符3,另一個進程也可以用3。除了進程級的文件描述符表,系統(tǒng)還需要維護另外兩張表:打開文件表、i-node 表。這兩張表存儲了每個打開文件的打開文件句柄(open file handle)。一個打開文件句柄存儲了與一個打開文件相關(guān)的全部信息。
系統(tǒng)級的打開文件描述符表:
當(dāng)前文件偏移量(調(diào)用read()和write()時更新,或使用lseek()直接修改)
打開文件時的標(biāo)識(open()的flags參數(shù))
文件訪問模式(如調(diào)用open()時所設(shè)置的只讀模式、只寫模式或讀寫模式)
與信號驅(qū)動相關(guān)的設(shè)置
對該文件i-node對象的引用,即i-node 表指針
文件系統(tǒng)的i-node表:
文件類型(例如:常規(guī)文件、套接字或FIFO)和訪問權(quán)限
一個指針,指向該文件所持有的鎖列表
文件的各種屬性,包括文件大小以及與不同類型操作相關(guān)的時間戳
文件描述符、打開的文件句柄以及i-node之間的關(guān)系如下圖:
在進程 A 中,文件描述符 1 和 20 都指向了同一個打開文件表項,標(biāo)號為 23(指向了打開文件表中下標(biāo)為 23 的數(shù)組元素),這可能是通過調(diào)用 dup()、dup2()、fcntl() 或者對同一個文件多次調(diào)用了 open() 函數(shù)形成的。
進程 A 的文件描述符 2 和進程 B 的文件描述符 2 都指向了同一個文件,這可能是在調(diào)用 fork() 后出現(xiàn)的(即進程 A、B 是父子進程關(guān)系),或者是不同的進程獨自去調(diào)用 open() 函數(shù)打開了同一個文件,此時進程內(nèi)部的描述符正好分配到與其他進程打開該文件的描述符一樣。
進程 A 的描述符 0 和進程 B 的描述符 3 分別指向不同的打開文件表項,但這些表項均指向 i-node 表的同一個條目(標(biāo)號為 1976); 換言之,它們指向了同一個文件。 發(fā)生這種情況是因為每個進程各自對同一個文件發(fā)起了 open() 調(diào)用。 同一個進程兩次打開同一個文件,也會發(fā)生類似情況。
這就說明:同一個進程的不同文件描述符可以指向同一個文件; 不同進程可以擁有相同的文件描述符; 不同進程的同一個文件描述符可以指向不同的文件(一般也是這樣,除了 0、1、2 這三個特殊的文件); 不同進程的不同文件描述符也可以指向同一個文件。
Linux系統(tǒng)文件描述符示例
比如在Linux上用 vim test.py 打開一個文件,保持打開狀態(tài),再新打開一個新的shell,輸入命令pidof vim 獲取vim進程的pid號,然后 ll /proc/$pid/fd 查看vim 進程所使用的文件描述符列表。
/dev/pts是遠程登錄(telnet,ssh等)后創(chuàng)建的控制臺設(shè)備文件所在的目錄。 因為我是通過Xshell遠程登錄的,所以標(biāo)準(zhǔn)輸入0,標(biāo)準(zhǔn)輸出1,標(biāo)準(zhǔn)錯誤2的文件描述符都指向虛擬終端控制臺 /dev/pts/6 。 再看下面是新打開的 test.py 的文件描述符,竟然是4,說好的從3開始呢?
因為vim這種編輯器的原理是先打開源文件并拷貝,然后關(guān)閉源文件再打開自己的副本,修改完文件保存的時候直接將副本重命名覆蓋源文件。 所以打開源文件的時候用的文件描述符3,然后打開自己的副本是時候就該用文件描述符4了,然后關(guān)閉源文件,文件描述符3就被釋放了,我們查看的時候就只剩下了4,這里它指向的是vim創(chuàng)建的副本文件。
審核編輯:湯梓紅
-
內(nèi)核
+關(guān)注
關(guān)注
3文章
1402瀏覽量
40904 -
Linux
+關(guān)注
關(guān)注
87文章
11412瀏覽量
212247 -
Linux系統(tǒng)
+關(guān)注
關(guān)注
4文章
601瀏覽量
28137 -
文件
+關(guān)注
關(guān)注
1文章
575瀏覽量
25107 -
描述符
+關(guān)注
關(guān)注
0文章
3瀏覽量
6149
原文標(biāo)題:一文搞懂文件描述符
文章出處:【微信號:aming_linux,微信公眾號:阿銘linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
USB描述符詳解
傳遞文件描述符是什么?
ARM中,Linux 文件描述符到底是什么?
usb標(biāo)準(zhǔn)描述符之技巧
USB HID報告及報告描述符簡介
Descriptor描述符解釋
Linux中文件及文件描述符概述
USB設(shè)備鍵值表描述符說明資料免費下載

USB各描述符之間的依賴是怎么樣的

科普一下什么是USB的描述符
Gadget框架構(gòu)造描述符

從獲取描述符的角度理解Gadget框架

Python的優(yōu)雅之處:Descriptor(描述符)

評論