0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文搞懂文件描述符

阿銘linux ? 來源:阿銘linux ? 2023-02-10 13:56 ? 次閱讀

Linux中的文件描述符

我們知道在Linux系統(tǒng)中一切皆可以看成是文件,文件又可分為:普通文件、目錄文件、鏈接文件和設(shè)備文件。在操作這些所謂的文件的時(shí)候,我們每操作一次就找一次名字,這會(huì)耗費(fèi)大量的時(shí)間和效率。所以Linux中規(guī)定每一個(gè)文件對(duì)應(yīng)一個(gè)索引,這樣要操作文件的時(shí)候,我們直接找到索引就可以對(duì)其進(jìn)行操作了。

e699e7d8-a8db-11ed-bfe3-dac502259ad0.png

文件描述符(file descriptor)就是內(nèi)核為了高效管理這些已經(jīng)被打開的文件所創(chuàng)建的索引,其是一個(gè)非負(fù)整數(shù)(通常是小整數(shù)),用于指代被打開的文件,所有執(zhí)行I/O操作的系統(tǒng)調(diào)用都通過文件描述符來實(shí)現(xiàn)。同時(shí)還規(guī)定系統(tǒng)剛剛啟動(dòng)的時(shí)候,0是標(biāo)準(zhǔn)輸入,1是標(biāo)準(zhǔn)輸出,2是標(biāo)準(zhǔn)錯(cuò)誤。這意味著如果此時(shí)去打開一個(gè)新的文件,它的文件描述符會(huì)是3,再打開一個(gè)文件文件描述符就是4......

Linux內(nèi)核對(duì)所有打開的文件有一個(gè)文件描述符表格,里面存儲(chǔ)了每個(gè)文件描述符作為索引與一個(gè)打開文件相對(duì)應(yīng)的關(guān)系,簡(jiǎn)單理解就是下圖這樣一個(gè)數(shù)組,文件描述符(索引)就是文件描述符表這個(gè)數(shù)組的下標(biāo),數(shù)組的內(nèi)容就是指向一個(gè)個(gè)打開的文件的指針。

上面只是簡(jiǎn)單理解,實(shí)際上關(guān)于文件描述符,Linux內(nèi)核維護(hù)了3個(gè)數(shù)據(jù)結(jié)構(gòu):

進(jìn)程級(jí)的文件描述符表

系統(tǒng)級(jí)的打開文件描述符表

文件系統(tǒng)的i-node表

一個(gè) Linux 進(jìn)程啟動(dòng)后,會(huì)在內(nèi)核空間中創(chuàng)建一個(gè) PCB 控制塊,PCB 內(nèi)部有一個(gè)文件描述符表(File descriptor table),記錄著當(dāng)前進(jìn)程所有可用的文件描述符,也即當(dāng)前進(jìn)程所有打開的文件。進(jìn)程級(jí)的描述符表的每一條記錄了單個(gè)進(jìn)程所使用的文件描述符的相關(guān)信息,進(jìn)程之間相互獨(dú)立,一個(gè)進(jìn)程使用了文件描述符3,另一個(gè)進(jìn)程也可以用3。除了進(jìn)程級(jí)的文件描述符表,系統(tǒng)還需要維護(hù)另外兩張表:打開文件表、i-node 表。這兩張表存儲(chǔ)了每個(gè)打開文件的打開文件句柄(open file handle)。一個(gè)打開文件句柄存儲(chǔ)了與一個(gè)打開文件相關(guān)的全部信息。

系統(tǒng)級(jí)的打開文件描述符表:

當(dāng)前文件偏移量(調(diào)用read()和write()時(shí)更新,或使用lseek()直接修改)

打開文件時(shí)的標(biāo)識(shí)(open()的flags參數(shù)

文件訪問模式(如調(diào)用open()時(shí)所設(shè)置的只讀模式、只寫模式或讀寫模式)

信號(hào)驅(qū)動(dòng)相關(guān)的設(shè)置

對(duì)該文件i-node對(duì)象的引用,即i-node 表指針

文件系統(tǒng)的i-node表:

文件類型(例如:常規(guī)文件、套接字或FIFO)和訪問權(quán)限

一個(gè)指針,指向該文件所持有的鎖列表

文件的各種屬性,包括文件大小以及與不同類型操作相關(guān)的時(shí)間戳

文件描述符、打開的文件句柄以及i-node之間的關(guān)系如下圖:

e6ac3960-a8db-11ed-bfe3-dac502259ad0.png

在進(jìn)程 A 中,文件描述符 1 和 20 都指向了同一個(gè)打開文件表項(xiàng),標(biāo)號(hào)為 23(指向了打開文件表中下標(biāo)為 23 的數(shù)組元素),這可能是通過調(diào)用 dup()、dup2()、fcntl() 或者對(duì)同一個(gè)文件多次調(diào)用了 open() 函數(shù)形成的。

進(jìn)程 A 的文件描述符 2 和進(jìn)程 B 的文件描述符 2 都指向了同一個(gè)文件,這可能是在調(diào)用 fork() 后出現(xiàn)的(即進(jìn)程 A、B 是父子進(jìn)程關(guān)系),或者是不同的進(jìn)程獨(dú)自去調(diào)用 open() 函數(shù)打開了同一個(gè)文件,此時(shí)進(jìn)程內(nèi)部的描述符正好分配到與其他進(jìn)程打開該文件的描述符一樣。

進(jìn)程 A 的描述符 0 和進(jìn)程 B 的描述符 3 分別指向不同的打開文件表項(xiàng),但這些表項(xiàng)均指向 i-node 表的同一個(gè)條目(標(biāo)號(hào)為 1976); 換言之,它們指向了同一個(gè)文件。 發(fā)生這種情況是因?yàn)槊總€(gè)進(jìn)程各自對(duì)同一個(gè)文件發(fā)起了 open() 調(diào)用。 同一個(gè)進(jìn)程兩次打開同一個(gè)文件,也會(huì)發(fā)生類似情況。

這就說明:同一個(gè)進(jìn)程的不同文件描述符可以指向同一個(gè)文件; 不同進(jìn)程可以擁有相同的文件描述符; 不同進(jìn)程的同一個(gè)文件描述符可以指向不同的文件(一般也是這樣,除了 0、1、2 這三個(gè)特殊的文件); 不同進(jìn)程的不同文件描述符也可以指向同一個(gè)文件。

Linux系統(tǒng)文件描述符示例

比如在Linux上用 vim test.py 打開一個(gè)文件,保持打開狀態(tài),再新打開一個(gè)新的shell,輸入命令pidof vim 獲取vim進(jìn)程的pid號(hào),然后 ll /proc/$pid/fd 查看vim 進(jìn)程所使用的文件描述符列表。

e6c40630-a8db-11ed-bfe3-dac502259ad0.png

/dev/pts是遠(yuǎn)程登錄(telnet,ssh等)后創(chuàng)建的控制臺(tái)設(shè)備文件所在的目錄。 因?yàn)槲沂峭ㄟ^Xshell遠(yuǎn)程登錄的,所以標(biāo)準(zhǔn)輸入0,標(biāo)準(zhǔn)輸出1,標(biāo)準(zhǔn)錯(cuò)誤2的文件描述符都指向虛擬終端控制臺(tái) /dev/pts/6 。 再看下面是新打開的 test.py 的文件描述符,竟然是4,說好的從3開始呢?

因?yàn)関im這種編輯器的原理是先打開源文件并拷貝,然后關(guān)閉源文件再打開自己的副本,修改完文件保存的時(shí)候直接將副本重命名覆蓋源文件。 所以打開源文件的時(shí)候用的文件描述符3,然后打開自己的副本是時(shí)候就該用文件描述符4了,然后關(guān)閉源文件,文件描述符3就被釋放了,我們查看的時(shí)候就只剩下了4,這里它指向的是vim創(chuàng)建的副本文件。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1372

    瀏覽量

    40293
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11304

    瀏覽量

    209535
  • Linux系統(tǒng)
    +關(guān)注

    關(guān)注

    4

    文章

    593

    瀏覽量

    27403
  • 文件
    +關(guān)注

    關(guān)注

    1

    文章

    566

    瀏覽量

    24748
  • 描述符
    +關(guān)注

    關(guān)注

    0

    文章

    3

    瀏覽量

    6059

原文標(biāo)題:一文搞懂文件描述符

文章出處:【微信號(hào):aming_linux,微信公眾號(hào):阿銘linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    USB描述符詳解

    對(duì)于實(shí)現(xiàn)USB功能的項(xiàng)目,不管是實(shí)現(xiàn)CDC,大容量存儲(chǔ)、HID等都必須使用實(shí)現(xiàn)USB標(biāo)準(zhǔn)描述符,從而實(shí)現(xiàn)USB枚舉過程。這里共享個(gè)USB描述符的詳解。
    發(fā)表于 06-12 14:46

    傳遞文件描述符是什么?

    我買了本書《Linux網(wǎng)絡(luò)編程》。 看到第11章高級(jí)套接字。有個(gè)例子,傳遞文件描述符。 其中,進(jìn)程A根據(jù)用戶輸入的文件名打開個(gè)
    發(fā)表于 05-07 02:18

    ARM中,Linux 文件描述符到底是什么?

    個(gè) Linux 進(jìn)程啟動(dòng)后,會(huì)在內(nèi)核空間中創(chuàng)建個(gè) PCB 控制塊,PCB 內(nèi)部有個(gè)文件描述符表(File descriptor tab
    發(fā)表于 10-23 16:11

    usb標(biāo)準(zhǔn)描述符之技巧

    usb標(biāo)準(zhǔn)描述符之技巧 USB是個(gè)通用的總線,端口都是統(tǒng)的。但是USB設(shè)備卻各種各樣,例如USB鼠標(biāo),USB鍵盤,U盤等等,那么USB主機(jī)是如何識(shí)別出不同的設(shè)備的呢?這就要依賴
    發(fā)表于 04-12 11:09 ?1532次閱讀

    USB HID報(bào)告及報(bào)告描述符簡(jiǎn)介

    在USB中,USB HOST是通過各種描述符來識(shí)別設(shè)備的,有設(shè)備描述符,配置描述符,接口描述符,端點(diǎn)描述符,字符串
    發(fā)表于 04-12 11:13 ?4041次閱讀

    Descriptor描述符解釋

    Descriptor即描述符,是個(gè)完整的數(shù)據(jù)結(jié)構(gòu),可以通過C語言等編程實(shí)現(xiàn),并存儲(chǔ)在USB設(shè)備中,用于描述個(gè)USB設(shè)備的所有屬性,USB主機(jī)是通過
    發(fā)表于 07-16 09:39 ?2645次閱讀

    Linux中文件文件描述符概述

    、鏈接文件和設(shè)備文件。 那么,內(nèi)核如何區(qū)分和引用特定的文件呢?這里用到了個(gè)重要的概念文件描述符
    發(fā)表于 10-18 14:35 ?0次下載

    USB設(shè)備鍵值表描述符說明資料免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是USB設(shè)備鍵值表描述符說明資料免費(fèi)下載包括了:1.設(shè)備描述符的結(jié)構(gòu),2. 配置描述符的結(jié)構(gòu),3. 接口描述符的結(jié)構(gòu),4. HID
    發(fā)表于 07-16 16:56 ?35次下載
    USB設(shè)備鍵值表<b class='flag-5'>描述符</b>說明資料免費(fèi)下載

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

    USB 是個(gè)通用的總線,端口都是統(tǒng)的。但是USB 設(shè)備卻各種各樣,例如USB 鼠標(biāo), USB鍵盤, U盤等等,那么USB 主機(jī)是如何識(shí)別出不同的設(shè)備的呢?這就要依賴于描述符了。USB 的描述符主要有設(shè)備
    發(fā)表于 07-23 16:53 ?8次下載
    USB各<b class='flag-5'>描述符</b>之間的依賴是怎么樣的

    Linux系統(tǒng)編程中的文件描述符調(diào)用

    文件描述符 進(jìn)程每打開個(gè)文件的時(shí)候,會(huì)獲得該文件文件描述
    的頭像 發(fā)表于 09-02 09:50 ?1682次閱讀
    Linux系統(tǒng)編程中的<b class='flag-5'>文件</b><b class='flag-5'>描述符</b>調(diào)用

    科普下什么是USB的描述符

    以及行為呢?這就要通過描述符來實(shí)現(xiàn)了。那么什么是USB的描述符呢?其實(shí)就是些傳遞的協(xié)議信息,比如設(shè)備的類型、廠商ID、產(chǎn)品ID、端點(diǎn)情況、版本號(hào)等信息。 既然描述符是協(xié)議信息,那么不
    的頭像 發(fā)表于 12-02 14:41 ?3967次閱讀

    Gadget框架構(gòu)造描述符

    假設(shè)你要【模擬】個(gè) USB 設(shè)備: 這個(gè) USB 設(shè)備含有廠家信息:它記錄在設(shè)備描述符里,所以設(shè)備描述符應(yīng)該由你提供 這個(gè)芯片可能有多種配置,這也是由你決定,所以配置描述符應(yīng)該由你提
    的頭像 發(fā)表于 07-13 11:34 ?652次閱讀
    Gadget框架構(gòu)造<b class='flag-5'>描述符</b>

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

    操作: 使用控制傳輸,讀取設(shè)備信息(設(shè)備描述符):第次讀取時(shí),它只需要得到 8 字節(jié)數(shù)據(jù),因?yàn)榈?8 個(gè)數(shù)據(jù)表示端點(diǎn) 0 能傳輸?shù)淖畲髷?shù)據(jù)長(zhǎng)度。 Host 分配地址給設(shè)備,然后把新地址發(fā)給設(shè)備。 使用新地址,重新讀取設(shè)備描述符
    的頭像 發(fā)表于 07-13 11:38 ?937次閱讀
    從獲取<b class='flag-5'>描述符</b>的角度理解Gadget框架

    基于DWC_ether_qos的以太網(wǎng)驅(qū)動(dòng)開發(fā)-描述符格式介紹

    前面我們介紹了描述符鏈表的工作模式,重點(diǎn)是了解環(huán)形鏈表是如何環(huán)形的,以及相關(guān)的寄存器。驅(qū)動(dòng)編寫就需要更進(jìn)步,了解描述符的具體內(nèi)容,即4個(gè)描述符的每個(gè)字段的含義。
    的頭像 發(fā)表于 09-04 14:14 ?2673次閱讀
    基于DWC_ether_qos的以太網(wǎng)驅(qū)動(dòng)開發(fā)-<b class='flag-5'>描述符</b>格式介紹

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

    語法糖的實(shí)現(xiàn)上也有使用到(在下面的文章會(huì)一一介紹)。 當(dāng)你點(diǎn)進(jìn)這篇文章時(shí) 你也許沒學(xué)過描述符,甚至沒聽過描述符。 或者你對(duì)描述符只是知半解 無論你是哪種,本篇都將帶你全面的學(xué)習(xí)
    的頭像 發(fā)表于 11-02 10:52 ?1015次閱讀
    Python的優(yōu)雅之處:Descriptor(<b class='flag-5'>描述符</b>)