Linux 檔案系統的資料結構

我們在開發應用系統或寫程式時, 大多會使用到檔案來存取資料, 雖然目前許多應用系統會直接連接資料庫, 但是資料庫也會使用檔案對資料做存取的動作, 因此檔案系統在大部份作業系統中都是一個重要的部分.

在 Linux 或其他 Unix-Based 的系統中, C 語言是最主要的語言. 在 C 語言中關於檔案的功能大部份都透過 Standard I/O Library 來完成 (也就是最常見的 printf 和 scanf 等 function). 在此我們要介紹的是更低階的檔案功能, 一般稱之為 File I/O, 這些功能都是直接作系統呼叫. 在 File I/O, 開啟檔案是使用 open 這個 function (在Standard I/O 是使用 fopen). 開檔成功後系統會傳回一個叫做 File Descriptor (FD) 的整數, 後續關於這個檔案的動作及功能都要使用這個 FD, 如檔案讀寫等, 都要傳入這個FD當做參數.  FD 基本上是一個Index, 而 FD 也是檔案系統的資料結構中, 唯一使用者程式能夠看到的部份. 開啟檔案相關的資料結構如下圖所示.  需要注意的是圖中稱為 Table 的資料結構其實都不一定真正使用 Table 的形式.

在 Linux 中, 一個 Process 的相關資訊都會存放在一個 task_struct 的資料結構中 (定義於 include/linux/sched.h 中), 這個資料結構就是一般熟知的 Process Table 的組成元素. 在 task_struct 中, 有一個 Pointer 指向 files_struct 這個資料結構(定義於 include/linux/fdtable.h), 在 files_struct 中包含有圖中的 FD table, 這是由一個叫做 file 的資料結構的pointer 所構成的 Array (file 的結構定義於 include/linux/fs.h).  系統就是透過 FD 來找到圖中所示 File Table 中的 file 的pointer.  在 file 的資料結構中, 有一個變數 f_pos, 用來表示 current file offset, 也就是這個檔案下一次讀寫的啟始位置.  因此若有兩個 FD 指到相同的 file 結構, 他們將會共用相同的 file offset, 因此透過其中一個 FD 去對檔案做讀寫後, 再用另一個 FD 去讀寫檔案(可能是另一個 process) 會從新的位置開始.  在 file 結構的另一個變數 f_inode, 會指到 inode 的資料結構(inode的基本資訊定義於 include/linux/fs.h, 但是不同的檔案系統細部結構會有差異).  在Linux 以及 Unix中, 一個 inode 代表著一個檔案, inode 會存放所有關於這個檔案的完整資訊, 例如檔案的 owner 以及檔案存放在硬碟的位置等.

下面用檔案開啟的動作來簡略說明這些資料結構彼此之間的連結.  當要 open 一個檔案時, 所做的事情大致上是這樣的:

  1. 先檢查 open_flags, 這裏的 flags 主要是看看是否 Create新檔, 檔案是否共享等等 (fs/open.c)
  2. 透過 files_struct中的 fdtable (即圖中的 FD table), 選取一個空的 FD (fs/file.c)
  3. 產生一個 file 資料結構的物件並將之存到File table, 然後再把它 link 到相對應的 inode (namei.c)
  4. 取得 File table 的這個 file物件的 pointer, 並將這個 file pointer加到 FD array 中 (file.c ).

這樣就完成了開啟檔案的動作, 在後續對檔案的動作, 如 read, write 等, 就透過這個 FD 拿到檔案的所有資訊.

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *