Linux檔案描述符

fasionchan發表於2018-08-08

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

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

小菜學程式設計

Linux檔案描述符

相關文章