虛擬檔案系統(virtual filesystem,VFS)
/ VFS = vee-eff-ess /
想像不論一個檔案躺在硬碟上、躺在以不同格式格式化的 USB 隨身碟上、躺在網路分享上,甚至躺在根本不是真實磁碟的東西上(例如 /proc),你都用同一種方式去開啟它。你打 open()、read(),它就是能用。這種一致並非偶然:核心裡坐著一個轉譯層,把所有這些儲存系統之間的差異藏在一組共通的操作之後。這一層就是虛擬檔案系統,通常簡稱 VFS。
具體而言,VFS 定義了少數幾種記憶體中的物件,每個真實檔案系統都必須提供:一個超級區塊(superblock,每個掛載的檔案系統一個,描述整體)、一個索引節點(inode,每個檔案一個,存放其後設資料)、一個目錄項(dentry,目錄中每個名字一個,把名字連到 inode)、以及一個檔案物件(file,每個已開啟的檔案描述符一個,存放目前的讀寫位置)。每個真實檔案系統——ext4、XFS、Btrfs、FAT、NFS——都提供一張函式指標表,說明該操作實際上怎麼做。所以當你呼叫 read(fd, ...),核心找到該檔案物件、循其 inode,呼叫那個 inode 的讀取操作,再分派進對應檔案系統的程式碼。應用程式從不知道是哪個檔案系統回應的。
為何重要:VFS 正是為何單一組 POSIX 呼叫(open、read、write、close、stat、rename)能跨越數十種截然不同的儲存後端運作,也是為何你能把一個檔案系統掛載進另一個的目錄樹裡。一個常見的誤解是把 VFS 本身當成一個會儲存資料的檔案系統——它在磁碟上什麼都不存。它純粹是一個由函式指標與快取物件組成、存在於 RAM 中的抽象層;真正的位元組住在底下那個具體的檔案系統裡。
open("/mnt/usb/a.txt") -> VFS 路徑走訪 -> dentry -> inode -> ext4 inode_operations->lookup open("/proc/cpuinfo") -> VFS 路徑走訪 -> dentry -> inode -> procfs file_operations->read
同一個 open() 透過單一 VFS 介面抵達兩個完全不同的檔案系統。
VFS 物件是只存在於 RAM 的快取,不是磁碟上的真相。VFS 的 inode 是核心對某檔案後設資料的記憶體副本;權威的 inode 住在磁碟上,回寫之前兩者可能短暫不一致。