Linux 核心101:虛擬檔案系統的使命

長江CJ發表於2019-05-11

本文參考了:

  • 《Understanding the Linux Kernel, Third Edition》12.1章

簡介

Linux 的成功有一部分原因在於能夠很好的支援不同的檔案系統,你能夠輕鬆透明地把 Windows、其他 Unix 系統、甚至是佔有極小份額的 Amiga 使用的檔案系統 mount 到Linux 的檔案系統中。這是通過Virtual Filesystem(以下簡稱 VFS)實現的。

VFS 背後的 idea 是在 kernel 中抽象出不同檔案系統,針對具體的檔案系統,Linux kernel 實現具體的操作方法。當系統呼叫readwrite發生時,kernel 根據操作的具體檔案系統,比如 native Linux檔案系統、NTFS(Windows NT)等,呼叫相對應的函式。

例項:cp

要執行一個cp指令:

cp /floppy/TEST /tmp/test
複製程式碼

其中/floppy是一個 mount 的MS-DOS檔案系統,而/tmp是 ext2。VFS 就是應用程式和底層檔案系統實現之間的一個抽象層cp不需要知道/floppy/TEST/tmp/test的檔案系統型別,它只需要呼叫標準的系統呼叫,比如readwrite這些,把底層檔案系統不同帶來的複雜度交給 kernel

示例的程式碼如下:

inf = open("/floppy/TEST", O_RDONLY, 0);
outf = open("/tmp/test",
       O_WRONLY|O_CREAT|O_TRUNC, 0600);
do {
    i = read(inf, buf, 4096);
    write(outf, buf, i);
  } while (i);
close(outf);
close(inf);
複製程式碼

示意圖:

Linux 核心101:虛擬檔案系統的使命

程式碼和截圖來源於 《Understanding the Linux Kernel, Third Edition》 P457

VFS 支援的檔案系統

VFS 支援嗯檔案系統一共分為下面三大類:

  1. Disk-based FS

本地的 disk。包括:

  • ext2, etx3, ext4
  • Unix 家族,比如 sysv 檔案系統、UFS(BSD,solaris)、MINIX等
  • Microsoft 檔案系統,比如 MS-DOS、NTFS
  • ISO9660 CD-ROM(之前的High Sierra Filesystem)
  • 其他冷門
  1. Network FS

這一類支援訪問遠端的檔案系統,比如 NFS、Coda、AFS 等。

  1. Special FS

/proc虛擬檔案系統。

通常來說,root 目錄為 Linux 原生的ext2ext3ext4,其他型別的檔案系統通過mount形式 mount 到某個特定子目錄。

Common File Model

VFS 背後的核心idea: 用common file model表示所有現實中的FS。這個模型嚴格使用原生Unix FS 模型,每個特定的 FS 都需要將自己的硬體結構翻譯成 common file model。

比如在 common file model 中,目錄也被看做檔案,包含其他的檔案盒目錄。然而,一些非 Unix 的 FS,使用的是 file allocation table(FAT),這種情況下,目錄不是檔案。但是為了遵循 common file model的規則,Linux 對這種 FAT-based 的 FS,必須能夠抽象出一個遵循common file model 的介面。

更加具體點,Linux kernel 在處理readioctl這些系統呼叫的時候,不能直接硬編碼,使用某個特定的底層函式。kernel實際上針對每一個操作,使用的是一個指標,這個指標指向了針對此檔案系統專門的處理函式。

讓我們來看看kernel 是如何完成上面提到的cp操作的。

應用層呼叫read(),kernel 實際上會呼叫sys_read() service routine(其他的系統呼叫也一樣)。MS-DOS FS 的檔案被 kernel memory 中的一個資料結構表示,這個資料結構包含一個f_op欄位,指向的是針對 MS-DOS 的 read 函式。sys_read()找到這個函式然後呼叫它。所以整個過程可以看作是:

read() -> sys_read() -> file data structure -> f_op -> read_for_msdos()
複製程式碼

呼叫write()也一樣,這個系統呼叫會觸發針對ext2 FS 的寫呼叫。

簡要來說,對於每個 open()建立的 file object,kernel 需要負責正確賦值此 file object的指標,指向針對此檔案系統的特定函式,然後呼叫這些函式。

CFM 包含哪些 object types

  • superblock object:包含的是 mounted FS 的資料。
  • indoe object:特定檔案的資料。對於 disk-based FS,這個 object 一般對應一個 file control block。每個 inode object 都有一個 inode number,唯一指定 FS 中的某一個檔案。
  • file object:一個open file 和程式之間的互動資訊。這個 object 只在程式開啟檔案的時候在kernel memory 中存在
  • dentry object:檔名到inode的對映,不同的 FS 有不同的底層實現。

Linux 核心101:虛擬檔案系統的使命

總結一下

VFS 是應用和特定檔案系統之間的一層抽象,有些操作能夠直接在 VFS 層完成,不需要涉及到底層的具體檔案系統。比如說,當程式close file的時候,disk 上的檔案本身是不會改變的,所以 VFS 只要把對應的 file 物件釋放掉就行了。再比如說,lseek()系統呼叫,改變的也是記憶體中的 file 物件,而不需要設計底層的檔案系統。

相關文章