Linux文件描述符

Linux通用I/O模型中,I/O操作系列函數(系統調用)都是圍繞一個叫做文件描述符的整數展開。這不禁讓人產生疑問:這個整數代表什麼?一個數值代表一個文件嗎?隨便傳一個整數進去調用可以嗎?

原文地址:https://learn-linux.readthedocs.io

玩轉Linux舊羣已滿,請加新羣:278378501

歡迎關注我們的公衆號:小菜學編程 (coding-fan)

解答以上疑問,需要更深入學習——文件描述符(File Descriptor)。

圖解

理解具體情況,需要了解由內核維護的3個數據結構:

  • 進程級文件描述符表(file descriptor table)
  • 系統級打開文件表(open file table)
  • 文件系統i-node表(i-node table)

這3個數據結構之間的關係如下圖所示:

fd-inode-diagram.png

文件描述符表

內核爲每個進程維護一個文件描述符表,該表每一條目都記錄了單個文件描述符的相關信息,包括:

  • 控制標誌(flags),目前內核僅定義了一個,即close-on-exec
  • 打開文件描述體指針

打開文件表

內核對所有打開的文件維護一個系統級別的打開文件描述表(open file description table),簡稱打開文件表。表中條目稱爲打開文件描述體(open file description),存儲了與一個打開文件相關的全部信息,包括:

  • 文件偏移量(file offset),調用read()write()更新,調用lseek()直接修改
  • 訪問模式,由open()調用設置,例如:只讀、只寫或讀寫等
  • i-node對象指針

i-node表

每個文件系統會爲存儲於其上的所有文件(包括目錄)維護一個i-node表,單個i-node包含以下信息:

  • 文件類型(file type),可以是常規文件、目錄、套接字或FIFO
  • 訪問權限
  • 文件鎖列表(file locks)
  • 文件大小
  • 等等

i-node存儲在磁盤設備上,內核在內存中維護了一個副本,這裏的i-node爲後者。副本除了原有信息,還包括:引用計數(從打開文件描述體)、所在設備號以及一些臨時屬性,例如文件鎖。

場景解析

上圖中,詳細描述了兩個進程諸多文件描述符,以及相互關係。

文件描述符複製

在進程A中,文件描述符1和文件描述符20都指向同一個打開文件描述體(標號23)。這很可能是通過調用dup()系列函數形成的。

文件描述符複製,在某些場景下非常有用,比如:標準輸入/輸出重定向。在shell下,完成這個操作非常簡單,大部分人都會,但是極少人思考過背後的原理。

大概描述一下需要的幾個步驟,以標準輸出(文件描述符爲1)重定向爲例:

  1. 打開目標文件,返回文件描述符n;
  2. 關閉文件描述符1;
  3. 調用dup將文件描述符n複製到1;
  4. 關閉文件描述符n;

子進程繼承文件描述符

進程A的文件描述符2和進程B的文件描述符2都指向同一個打開文件描述體(標號73)。這種情形很可能發生在調用fork()派生子進程之後,比如A調用fork()派生出B。這時,B作爲子進程,從父進程A繼承了文件描述符表,其中包括圖中標明的文件描述符2。這就是子進程繼承父進程打開的文件這句話的由來。

當然了,進程A通過Unix套接字將一個文件描述符傳遞給B也會出現類似的情形,但一般文件描述符數值是不一樣的。同時爲2要非常湊巧才發生。

下一步

更多文章請訪問:學習Linux

訂閱更新,獲取更多學習資料,請關注我們的 微信公衆號 :

小菜學編程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章