第 9 章 檔案系統

 

這章描述 Linux核心怎麼在它支援的檔案系統中維護檔案,描述虛擬檔案系統 ( VFS ) 講述了Linux 核心的真實檔案系統是怎麼被支援的。 Linux 的最重要的特徵之一是它的為許多不同的檔案系統的支援。這使其非常靈活從而與許多另外 的作業系統可以很好的共存。 在本書寫作的時候, Linux已支援 15 種檔案系統; ext , ext2 , xia , minix , umsdos ,msdos , vfat , proc , smb , ncp , iso9660 , sysv , hpfs , affs 及 ufs , 並且沒有疑問, 將來支援的檔案類型將被增加的更多。 在Linux中 ,因為它是Unix的一種,系統可以使用的不同檔案系統, 不能像Windows或DOS一樣通過設 備辨識器存取 ( 例如一個磁碟機數字或一個磁碟機命名 ), 而是它們被構建成為一個單一的層次樹 狀結構以作為代表檔案系統的實體。 Linux 通過安裝一個檔案系統將該新檔案系統加入它的檔案系 統樹中。所有的檔案系統, 不管是什麼類型,都安裝在檔案系統樹的一個目錄上並且該檔案系統之上 的檔案將掩蓋掉這個安裝目錄中原來存在的內容。這個目錄稱為安裝目錄或安裝點。當檔案系統被卸 掉之後,安裝目錄中原來的檔案才再次可見。 當磁碟被初始化時 ( 使用 fdisk , 例如 ) 磁碟上存在著一個分區結構把實體的磁碟劃分成很多邏輯 的分區結構。每個分區可以擁有一個單個的檔案系統, 例如一 EXT2 檔案系統。檔案系統通過在實體 設備上的目錄,軟聯接等等來組織檔案以形成一個邏輯的層次結構。能包含檔案系統的設備稱為塊設 備。 IDE 磁碟分區 /dev/hda1 , 系統中的第一個IDE 磁碟磁碟機分區, 是一個區塊設備。 Linux 檔案 系統認為這些區塊設備是塊的簡單的,線性的組合, 他們不知道(關心)底層的實體磁碟的幾何學分布。 一個讀區塊設備的請求到具體的實體參數的映射過程由區塊設備驅動程式來負責,如相應的磁軌,sector和 塊所在的柱面。 一個檔案系統,不管位於什麼具體的設備上,必須保持一個同樣的方式和介面來進行 操作。使用Linux的檔案系統時, 即使這些不同的檔案系統在不同的實體的媒介上,由不同的硬體控制 器控制著,對於系統用戶而言,應該是透明的,沒有關系的。檔案系統可能甚至不在本地的磁碟系統上 , 而是一個網路安裝的磁碟。考慮如下一個Linux系統,它的根檔案系統在一個SCSI磁碟上。 A E boot etc lib opt tmp usr C F cdrom fd proc root var sbin D bin dev home mnt lost+found 用戶和操作在上述檔案系統上的程式都不需要知道 /C 是一個安裝的 VFAT 檔案系統位於系統的第一個 IDE 磁碟上。在上述例子中, /E 是在第二 個IDE 控制器上的主IDE 磁碟。第一 IDE 控制器是否是一 個PCI控制器,第二個控制器是否是一個ISA控制器(控制 IDE CDROM 的那個),在這裡沒有關系。我能撥 號上網進入我工作的機器,使用一個數據機和 PPP通訊協定。在這種情況中我能遠程地裝我的 Alpha AXP Linux系統的檔案系統在上本地的/mnt/remote 目錄上. (譯者注:作者在這裡解釋了半天,其目的是讓讀者理解:檔案系統(File System)是作業系統中抽像出來 的一個概念。其具體的實體結構組織對於用戶和用戶程序是透明的,不用關心的。) 一個檔案系統的檔案是資料的集合。一個檔案系統不僅含有檔案系統中的檔案而且含有檔案系統的結構。 它包含Linux用戶和程序所能看見的檔案,目錄聯結,檔案保護信息等等。 而且它必須安全地保持那個信 息,作業系統的基本完整取決於它的檔案系統。沒人將使用隨機丟失資料和檔案的一個作業系統。 Minix , Linux 的第一個檔案系統有相當的侷限性並且缺乏很好的性能。 它的檔案名不能比 14 個字元長 ( 它仍然比 8.3 檔案名好一些 ) 並且最大的檔案大小是 64MBytes 。 64Mbytes 可能乍看之下似乎足夠大但是大檔案大小是必要的以用來保持資料函式庫系統。第一個,具體地說, 為Linux 設計的,檔案系統, 擴充檔案系統, 或 EXT , 在 1992 年 4 月被引入,其解決了很多問題但 是仍然缺乏一個很好的性能。 因此,在 1993 ,第二擴大檔案系統, 或 EXT2 , 被增加到Linux檔案系統中。 這個檔案系統將在本章被詳細描述。 當 EXT 檔案系統被增加進 Linux 時,一個重要的關於檔案系統的開發技術發生了。真實的檔案系統通過 一個叫做虛擬檔案系統(VFS)的介面層,而從作業系統和系統服務中被邏輯地分離開來。 VFS 允許 Linux 支援許多不同的, 檔案系統。每一個檔案系統提交一個相同的軟體介面給 VFS。 Linux 檔案系統的所有細節被軟體解釋從而所有的,不同的,檔案系統對Linux 核心,對在系統運行的程式而言 顯得相同。 Linux 的虛擬的檔案系統層允許你同時透明地安裝許多不同的檔案系統。 (譯者注:細心的讀者不難發現,在工業界,通過提供一個介面(Interface)標準,透明地屏蔽掉實現的 不同性,多樣性是一個常用的方法。如POSIX標準,PCI標準等等。這個思路幾乎可以在任何一個技術中 得到採用。標準是整合工業界競爭的必然手段和結果。) Linux虛擬檔案系統的實現要使得對檔案的存取要盡可能的快和高效。檔案和檔案中的資料要正確地被維護。 上述這兩個要求是互相限制的。 當檔案系統被安裝和使用時,Linux VFS 在記憶體中保存其信息。當檔案和 目錄被創造,寫和刪除時,在這些快取裡的資料要被修改更新,以正確地更新檔案系統。如果在運行的 核心中觀察檔案系統的資料結構,你將能看到資料塊正被檔案系統讀和寫。描述正在被存取的檔案和目錄 的資料結構,在核心中被創建和刪除。設備驅動程式總是在那裡存取和保存資料。這些快取(Cache)中最重 要的是是緩衝區快取(Buffer Cache), 它是一個檔案系統存取底層區塊設備的方法和途徑。當資料塊被存取時, 它們被放進緩衝區快取並且根據它們的狀態而放入各種各樣的隊列中。緩衝區快取不僅快取資料緩衝區, 它 也與區塊設備驅動程式一起管理非同步介面。 9.1 第二擴充檔案系統 ( EXT2 )
圖 9.1 : EXT2 檔案系統的實體的概觀
第二擴充檔案系統被設計 ( 由 Remy Card)作為 Linux 的一個可擴展的,強有力的檔案系統。它 也是到目前為止在 Linux領域最成功的檔案系統並且被目前Linux 的所有的分發(Distribution)所支援。 EXT2 檔案系統, 像很多檔案系統一樣,其構造的前提假設是檔案中保持的資料被放在資料塊中。這些 資料塊大小都一樣,並且, 盡管塊大小在不同的 EXT2 檔案系統之間可以變化,但當它被創造時(使用mke2fs), EXT2 中塊大小就被定下來 。每個檔案的大小都被調整為塊大小的整數倍。如果塊大小是 1024 個位元,那麼 1025個位元的一個檔案將占據 2 1024位元的塊。不幸的是,這意味著平均而言每個檔案將浪費半個資料塊。 通常在考慮計算時,記憶體和磁碟空間的使用率與CPU的使用效率之間是一種折衷(Trade off)。Linux ,與大 多數作業系統一樣,選擇相對低效的磁碟使用以便在 CPU 上減少負載(workload)。檔案系統中,不是所有的塊 都含有檔案資料, 其中一些必須被用來描述檔案系統的結構信息。 EXT2 通過inode 資料結構描述每個檔案。 並已此定義檔案系統的拓樸。一個inode 描述一個檔案中的資料占據哪些塊,檔案的修正時間,存取權利和文 件類型等等。EXT2 檔案系統中,每個檔案被 一個inode描述並且每個 inode 有一個唯一的數字標識。檔案系統 的inodes 一起被放在一個 inode 表中。 EXT2 目錄是一種特殊的檔案 ( 也被inodes 描述),包含一些指標, 指向目錄入口的各個檔案或子目錄的 inodes 。 圖9.1 給出了一個在一個區塊設備上占據一系列塊的EXT2檔案系統概觀。就每個檔案系統而言,區塊設備只是能被讀 並且寫的一系列資料塊而已。一個檔案系統不需要擔心一個資料塊放在實體的媒介上的何處。實體分布是設備的 設備驅動程式的工作。無論何時一個檔案系統需要從包含它的區塊設備讀信息或資料,它請求設備驅動程式讀出一 個整數倍數的資料塊。EXT2檔案系統劃分其占據的邏輯分區成為資料塊組(Block Group)。 除了保持其中的檔案和目錄的信息之外,每個組還複製那些對於檔案系統的完整性至關重要的信息和資料。這個 信息的備份是非常需要的當災難發生並且檔案系統需要恢復的時候。下面的章節將更詳細的描述每個資料塊組的 內容。 9.1.1 EXT2 Inode
圖 9.2 : EXT2 Inode
在 EXT2 檔案系統中, inode 是最基本的建構單位;檔案系統的每個檔案和目錄被一個並且僅僅被一個inode所描述。 每個塊組的inodes被存放在一個inode表中。該表與系統中的一張位元映射表一起,使得系統可以追蹤分配了的indoes和 沒有分配的inodes的情況。圖 9.2 顯示出一個 EXT2 inode 的格式, 在其包含的信息之中,它包含下列域: 模式(Mode) 這個域含有兩個信息;這inode描述什麼並且用戶擁有的允許。對EXT2而言 ,一個inode能描述檔案, 目錄,符號連接,區塊設備,字元設備或 FIFO。 擁有者信息(Owner Information) 這個檔案或目錄的主人的用戶和組辨識器。這允許檔案系統正確允許的該inode的各項存取。 大小(Size) 以位元為單位的檔案的大小。 時間標記(Timestamps ) inode 被創造的時間和它最後一次被修改的時間。 資料塊(Datablocks ) 到包含這個inode描述的資料的塊的指標。第一12個指標是到包含這inode所描述的資料的塊的指標。 最後3個指標包含間接的,越來越多層的,最後描述了資料的,實體塊的間接指標。例如, 兩倍間接塊指標 指向一個資料塊。該資料塊中每個入口又是指向一個資料塊指標的指標。這種方式意味著小於或等於12個數 據塊的檔案比更大的檔案存取起來要更快些。 應該注意的是, EXT2 inodes 可以描述特殊的設備檔案。這些不是真實的檔案而是程式能夠使用來存取設備的 handler。所有在/dev下的設備檔案都在那裡以允許程式存取 Linux 的設備。例如 mount 程式將想要安裝的設備檔案 作為一個參數來引用。 9.1.2 EXT2 超級塊(Superblock) Superblock 包含一個檔案系統的基本大小和其形狀的描述。檔案系統管理器使該信息來維持檔案系統。 當檔案系統被安裝時,通常僅僅在資料塊組 0 的 Superblock 被讀進記憶體。在系統的每個其他塊組中也含有一個 超級塊的副本拷貝以防止檔案系統崩潰。在其含有的信息之中: Magic Number 這允許安裝軟體根據這個域來檢查此確實是一個 EXT2 檔案系統的 Superblock 。目前的EXT2版本 是 0xEF53 . Revision Level 主和次Revision Level 使得安裝程式碼可以決定這個檔案系統是否只是特別地支援某個版本的檔案系統性能。 其特徵相容性域值可以幫助安裝程式碼決定哪些新特徵可以在這個檔案系統上被使用, Mount Count and Maximum Mount Count 這些域在一起,允許系統決定是否檔案系統應該被檢查。檔案系統被安裝時,安裝數每次被增加,並且 當它等於最大的安裝數時,系統將顯示警告消息“到達最大的安裝數目, 推荐運行e2fsck”。 Block Group Number 擁有該Superblock 的這個拷貝的塊組數字, Block Size 這個檔案系統的塊的大小, 例如 1024 個位元, Blocks per Group 在一個組中塊的數目。當檔案系統被創造時,像塊大小一樣這個值是被固定下來的, Free Blocks 在目前檔案系統中的空餘的塊的數目, Free Inodes 在目前檔案系統中的空餘的 Inodes 的數目。 First Inode 檔案系統中的第一個 inode 的 inode 號碼。在一個 EXT2 根檔案系統的第一個inode 將是目錄入 口項 / 目錄。 9.1.3 EXT2 組描述器 每個塊組(Block Group)有一個資料結構來描述它。像 Superblock 一樣,所有塊組的組描述器在每個塊組中有一份 拷貝以防止在檔案系統崩潰。 每個組描述器包含下列信息: 塊位元映射表(Blocks Bitmap) 目前塊組中塊的分配位元映射表的塊號碼。在塊分配和回收期間被使用。 Inode 位元映射表 目前塊組的 inode 分配位元映射表的塊號碼。這在 inode 分配和回收期間被使用, Inode 表 這個塊組的 inode 表的開始塊的塊號碼。每個 inode 由一個 EXT2 inode 資料結構來描述。 空餘塊數, 空餘 Inodes 數, 已使用的目錄數(Free Block count,Free Inodes count,Used directory count) 組描述器逐個存放並且一起組成為描述器表。每個塊組,在其Superblock 的拷貝以後包含組描述器的全部表項。 系統中僅僅第一個拷貝 ( 塊組 0 ) 實際上被 EXT2 檔案系統使用。另外的拷貝, 像 Superblock 的拷貝一樣, 只是以防主拷貝崩潰.(譯者注:讀者可以回憶DOS中的兩個FAT表的使用﹔當尋找一個檔案時,系統只用第一個FAT表﹔ 另外一個FAT表作備份使用以防FAT鏈結串列指標混亂。有趣的是DOS中並不保存多個0sector。總的來說,多個超級塊和組 描述器資料結構的使用是為了保証資料結構的一致性。如當使用fsck檢查檔案系統時,如兩個相應的資料結構不一致, 那就說明檔案系統非正常的操作發生,如調電,非正常關機等等。) 9.1.4 EXT2 目錄
圖 9.3 : EXT2 目錄
在 EXT2 檔案系統中,目錄是被用來創造並且在檔案系統中保持存取路徑到檔案的特殊檔案。圖 9.3 顯示出記憶體中一個目錄入口的概觀。 一個目錄檔案是一系列目錄入口的一張表, 每一個入口項包含下列信息: inode 為這個目錄入口項的 inode 號碼。這是被保存在塊組Inode 表中的inodes 的陣列的索引。 在圖 9.3 中, 檔案 file 的目錄入口 是一個指向inode i1 的指標。 名字長度(name length) 這個目錄入口的以位元記的長度,如16位元等等。(譯者注:換句話說,每個目錄項的長度是不定長的) 名字(name) 這個目錄入口的名字,如檔案的名字或子目錄的名字等等。 每個目錄的起先兩個入口項總是是“ . ”並且“ .. ”,分別意味著這個目前目錄和“上一級目錄” 的入口。 9.1.5 在一個 EXT2 檔案系統中尋找一個檔案 一個 Linux 檔案名的格式和 Unix 一樣。它是一系列由“ / “” )分開的目錄名組成,最後以檔案的名字結束。 例如一個檔案名是 /home/rusling/.cshrc, 在這裡/home 及 /rusling 是目錄名字。檔案的名字是 .cshrc . 像所有的其他的 Unix 系統一樣, Linux並不特別著重對檔案名的格式本身。它可以是任何長度,由可打印的字元組成。 為了發現代表一個檔案inode, 一個EXT2 系統必須一個目錄一次的逐層分析這個組合的檔案名的直到我們最終找到該 檔案。 我們需要的第一個 inode 是檔案系統根(root)的 inode。我們可以得到它的值在檔案系統的 superblock中 。 為了讀取一個 EXT2 inode ,我們必須在適當的塊組的 inode 表從尋找它。如果,例如, 根 inode 號碼是 42 , 我們將從塊組0的 inode 表中讀取第 42 個inode 。根 inode 為一個 EXT2 目錄, 換句話說 inode 作 為一個目錄。其指向的資料塊包含 EXT2 目錄入口的資料。 home只是"/"中許多目錄入口的一個。 從其在“/”中的入口項,我們可以得知描述其的inode 的號碼。我們必須讀 這個目錄 ( 首先讀它的 inode,然後從該inode指向的資料塊讀取"/home"下的目錄入口資料)來發現 rusling。從得到的資料中,我們得到/home/rusling 目錄 inode 的號碼的入口 。最後我們讀入指向描述目錄 /home/rusling的inode資料。並從其指向的資料塊中發現.csshrc的 inode 數值。從該inode中,我們可以定位包含 該檔案資料的資料塊。 9.1.6 在一個 EXT2 檔案系統中改變一個檔案的大小 檔案系統一個普遍的問題是檔案資料塊組織的碎片趨勢(譯者注:資料塊實體存放位置的不連續性,離散性)。保持 檔案的資料的塊在整個檔案系統中分布。這使得順序存取一個檔案的資料塊的效率隨著資料塊的分離越來越差。 EXT2 檔案系統通過將一個新分配的資料塊放在靠近目前塊的地方,或至少在一個同樣的塊組,來克服上述效率的問題。 只有當上述行為失敗時(譯者注:如目前塊組已滿),檔案系統才分配在另外的塊組的資料塊。 無論何時程序試圖寫資料進一個檔案, Linux 檔案系統檢查看資料將寫入的位置是否已越過檔案的最後分配的資料塊。 如果是的,它必須為這個檔案分配新資料塊。直到分配完成,程序不能運行;必須等到檔案系統分配一個新資料塊並且 將余下資料寫入到這個新的資料塊中之後。EXT2資料塊分配演算法要做的第一件事情是鎖住EXT2檔案系統的 Superblock。 分配和釋放資料塊都要改變superblock內的域值,檔案系統不能允許超過一個的 Linux 程序同時這種變化。如果另外 的程序更需要分配資料塊,它將必須等待直到這程序完成了。等待 superblock 的程序被暫停, 不能繼續運行,直到 superblock 的控制被它的目前的占有者所放棄。 superblock 的存取基於先來, 先服務的基礎(FIFO)並且一旦程序 獲得 superblock 的控制,它擁有該控制直到它完成了操作。獲得並鎖住了superblock後 , 程序檢查檔案系統中是否有 足夠的自由資料塊。如果沒有足夠的可分配實體資料塊, 分配塊的嘗試將失敗並且程序將放棄這個檔案系統的 superblock 控制。(譯者注:superlock或inode被讀進記憶體後是共享的資料區,所以在存取時要加鎖。在作業系統中, 檔案系統是個非常需要保護的資源。不同的檔案handler可以指向同一個檔案。對檔案的操作是一個完全並發的操作過程。 在一個程序讀一個檔案的同時,其內容可以被其他程序或同一個程序內部的執行緒(Thread)所改寫。因此作業系統核心 的鎖機制是非常重要的。譯者強烈建議讀者閱讀相關內部演算法。可參見貝齊的著作。) 如果在檔案系統中有足夠的自由塊, 程序試著分配一個。 如果 EXT2 檔案系統被設計成有預先分配資料塊的功能,我們可以從中取一個。預先分配的資料塊其實並不實 際上存在, 它們只是在分配的塊位元映射表中被預先保留而已。代表正在試圖分配資料塊給那個檔案的 VFS inode的新數 據塊有兩個EXT2 特定的域, prealloc_block 及 prealloc_count , preallocated 是第一個預先分配的資料塊 的塊號碼。preallocated是目前預先分配的資料塊已經有多少。如果目前沒有預先分配的塊或塊preallocation功能沒 被打開, EXT2 檔案系統必須從頭開始分配一個新塊。EXT2檔案系統首先查看在該檔案的最後那個資料塊之後的資料塊是 否是空餘的。從邏輯上而言, 這是分配方案中最有效的塊因為它使得做順序存取更加快捷。如果該塊不是空餘的,系統 擴大搜索範圍並且在該理想塊的64 塊範圍內尋找資料塊。這個尋找到的塊, 盡管不是最理想的,但還是相當靠近並且與 另外屬於這個檔案的其他資料塊屬於同一個資料塊組。 如果甚至上述塊也不是空餘的,程序開始依次在其他的塊組裡進行尋找直到它發現空餘的塊。塊分配程式碼在塊組中尋找 一個 有 8 個空餘的資料塊簇。如果它不能發現 8 個資料塊在一起, 它將要求設置較少些。如果需要或啟動了塊預分配 (preallocation)功能,它將更新 prealloc_block 及 prealloc_count位值(譯者注:系統總是盡力的要把檔案的資料塊 放在相鄰的實體位置以提高檔案資料尋找效率。這裡的機構是,如果一個連續8個資料塊或少點的連續資料塊被發現, 即使不預先分配占有,在下一次分配空間時,極有可能系統得到最佳的分配方案---連續分配。如果預約功能打開, 則確保下次分配的最佳性) 無論哪裡系統發現空餘的塊, 塊分配程式碼更新該目標塊組的塊位元映射表(譯者注:標記該實體塊已被占用。 請回憶在PC下使用NORTON 軟體查看磁碟空間使用時的情景)並且在緩衝區快取(Buffer cache)中分配一個資料緩衝區。 那個資料緩衝區被檔案系統支援的對應的設備辨識器唯一定位(1:1)並且與剛剛分配的實體塊號碼也是唯一對應的。 然後緩衝區的資料被清零-- zero'd,而且緩衝區的狀態被標記”dirty" 以表示該緩衝區的內容還沒被最後寫入 對應的實體磁碟塊。最後,superblock自己被標記作為”dirty”以表示已被改變,然後被解鎖。如果有任何程序 正在等待superblock ,在隊列中的第一個被允許再次運行並且將為它的檔案操作獲得 superblock 的獨占控制。 程序的資料被寫到新資料塊(譯者注:其實是先寫入其對應的資料緩衝區中),並且, 如果那個資料塊已被充滿,程序將重復上述塊分配行為從而得到一個新的資料塊. (譯者注:這裡講的superblock,indoe, buffer cache全是核心中的共享資料結構,所以存在與實體磁碟上的 映像的一致性問題。在檔案系統中,一個非常重要的是:所有的塊資料都是先寫入Buffer Cache。而Buffer Cache 也是被多程序,多執行緒所共享的。) 9.2 虛擬檔案系統 ( VFS )
圖 9.4 :虛擬的檔案系統的邏輯圖表
圖 9.4 顯示了Linux 核心的虛擬檔案系統與真實檔案系統的關系。虛擬檔案系統必須管理在任何時間被安裝的,不同的 檔案系統。為了做到這一點,它在核心中維持描述全部的資料結構為整個( 虛擬 ) 檔案系統和真實的, 安裝的檔案系統。 值得注意的是,VFS,像EXT2檔案系統一樣, 同樣使用 superblocks 和 inodes來描述系統的檔案。像 EXT2 inodes 一樣, VFS inodes 在系統內用來描述檔案和目錄;虛擬檔案系統的內容和結構拓樸。從現在起, 為了避免混亂, 我們將用VFS indoes VFS superblocks 以區別 EXT2 inodes 和 superblocks。 當每個檔案系統被初始化時,它向 VFS 登記自己。這個過程通常發生在當作業系統在系統引導時間初始化自己的時候。真實 的檔案系統要麼是被嵌入了核心或是作為可裝載的模組。系統模組當系統需要它們時被裝載, 因此,例如, 如果 VFAT 檔案 系統作為一個核心模組被實現,那麼只有當被裝載(mount)的時候,一個VFAT檔案系統才被裝入核心。當一個基於區塊設備的文 件系統被安裝時(這包括根檔案系統),VFS 必須讀入它的 superblock 。每種檔案系統類型的 superblock 讀例程必須了 解其相應檔案系統的拓樸組織結構並將該信息映射到 VFS superblock 資料結構之上。 VFS 保持系統中所有已安裝的檔案系 統的VFS superblocks並組織成一個鏈結串列。每個 VFS superblock包含相應的信息和能執行特殊功能的例程的指標。例如, 一個安裝了的 EXT2 檔案系統的 superblock 包含一個指向讀取一個特定的 EXT2 inode 結構的例程指標。這個 EXT2 inode 讀取例程, 像檔案系統的所有其他特定的 inode 讀例程一樣, 在一個 VFS inode 中填寫相關域。檔案系統中每個 VFS superblock 包含一個指標指向其相應的第一個 VFS inode 。對於根(“/”)檔案系統,這是代表的“/” 目錄的inode。 這個信息映射的過程對於 EXT2 檔案系統是很有效的但是對於另外其他的檔案系統其效率要差些。 當系統的程序存取目錄和檔案時,與 VFS inodes 處理相關的系統例程在系統核心中被調用。 例如, 鍵入 ls 以顯示一個目錄或 cat 以顯示一個檔案導致虛擬檔案系統尋找代表那個檔案系統的相應VFS inodes。 因為在系統中每個檔案和目錄都對應於一個VFS inode,因此會有很多 inodes 將反復的被存取。這些 inodes 被存放在使 它們的存取更快的 inode 快取。如果一 inode 不在 inode 快取,那麼特定的例程必須被請的一個檔案系統命令讀適當的 inode 緩衝中。如果一個inode不在inode緩衝中,則必須調用一個特定的例程來讀入一個inode。讀 inode 的行為導致一個 inode被放進 inode 快取中並且其他相續的對該inode的存取將使得該inode保持在快取中。不常用的 VFS inodes 會從核心 inode快取中被挪走。 所有的Linux檔案系統使用相同的的緩衝區快取(Buffer Cache)機制來緩衝來自底層的資料。這個機制使得檔案系統對實體 資料存儲設備的存取得到加快。 這個緩衝區快取是獨立於檔案系統的,被集成入 Linux 核心機制中用來分配和讀寫緩衝區和。這個機制的最大優點是它使得 Linux檔案系統獨立於底層的實體介質,獨立於設備驅動程式。所有的區塊設備在Linux 核心中登記自己,提供一個一致的,基 於塊的, 非同步的介面。即使復雜的SCSI 設備也如此。當真實的檔案系統要從底層實體設備讀取資料時,其結果是觸發一個塊 設備驅動程式向它們控制的設備發出讀實體塊的請求。集成在區塊設備介面裡的就是緩衝區快取。當檔案系統讀入了資料塊後, 它們被存放在這個全局的緩衝區快取中,被檔案系統和 Linux核心所共享。在其內的緩衝區資料通過塊號碼和對應於其設備的 辨識器被系統唯一標識。因此,如果同樣的資料經常被需要使用,資料將從緩衝區快取被檢索而非從磁碟讀入。一些設備支援 提前讀取功能,系統“猜測”要被讀取的資料塊並事先將其讀入到緩衝區緩衝中。 VFS 也保留一個存放目錄尋找的快取以便經常被使用的目錄的 inodes 能快速被發現。 作為一個試驗,試著列出你最近沒列出的一個目錄。你列出它的第一次, 你可以注意響應時間有一點停頓,但是 第二次列此目 錄時速度卻是非常快的。目錄快取並不存儲目錄的 inodes 本身;這些應該在 inode 快取中, 目錄快取只簡單地存儲目錄名到 其相應的indoe 號碼間的映射信息。 9.2.1 VFS Superblock 每個安裝了的檔案系統都被一個 VFS superblock 所表示;在其信息之中, VFS superblock 包含: 設備(Device) 這是這個檔案系統所依賴的區塊設備的設備辨識器。例如, /dev/hda1 , 系統中的第 一個 IDE 硬碟有一個設備辨識器 0x301 , Inode 指標 mounted inode 指標指向這個檔案系統的第一個 inode。 covered inode 指標指向代表這個檔案系統安裝點 目錄的 inode。根檔案系統的 VFS superblock 沒有 covered 指標, 塊大小(Blocksize ) 這個檔案系統的位元的塊大小, 例如 1024 個位元, Superblock 操作 一個指向這個檔案系統的一套 superblock 例程的一個指標。與其他信息在一起使用,這些例程被 VFS 用來 讀和寫該檔案系統的 inodes 和 superblocks 。 檔案系統類型(File System Type) 一個指向被安裝檔案系統中file_system_type 資料結構的一個指標, File System specific 一個指標指向這個檔案系統所特定需要的一些信息, 9.2.2 VFS Inode 像 EXT2 檔案系統一樣, VFS系統中每個檔案, 目錄等等被一個而且僅僅被一個 VFS inode 所表示。 通過一些特殊的檔案系統例程,每個 VFS inode 的構建信息都來自於底層的檔案系統。 VFS inodes 僅僅在核心中, 記憶體中才存在,並且只當他們對系統有用時才存在。 VFS inodes 包含下列域: 設備(device) 這是保持該VFS inode 所代表的檔案所在的設備的設備辨識器 inode 號碼 這是該 inode 的號碼並且此號碼在這個檔案系統以內是唯一的。device 和 inode 號碼的組合在虛擬文 件系統中是唯一的, 模式(mode) 像EXT2中這個域一樣,它描述這個 VFS inode 代表了什麼和相應的存取權利。 用戶 ids 該VFS inode擁有者的辨識器, 時間 創造, 修正和寫的時間, 塊大小 這個檔案的塊的大小, 例如 1024 個位元, inode 操作 指向一塊例程位址的一個指標。這些例程對檔案系統是特定的並且它們可以為這個 inode 完成相關操作, 例如, 截斷 被這個 inode 所代表的檔案。 count 系統中目前使用這個 VFS inode 的統計數字。一個count 是0的inode 是空餘的或可以被從記憶體中拋棄的。 鎖(lock) 這個域被用來鎖住一個 VFS inode , 例如, 當它正從檔案系統中被讀取時, dirty 顯示這 VFS inode 是否被寫了, 如果是,底層相應的檔案系統需要修改,以保持一致性, 檔案系統特定的信息(file system specific information) 9.2.3 登記檔案系統
圖 9.5 :登記的檔案系統
當你構造 Linux 核心時,你會被問到你是否想要構建支援的每個檔案系統。當核心被構造時,檔案系統初始程式碼中含有 所有被構造檔案系統的初始化程式碼的調用入口。 Linux 檔案系統也可以作為模組來被構造,並且, 在這種情況中,它們可以是當需要時或手工安載時(使用insmod命令), 才被裝入。無論何時一個檔案系統模組被裝載,它向核心登記自己﹔當被卸掉時,從核心中撤消登記。每個檔案系統的 初始化程式碼在虛擬檔案系統VFS中登記自己,通過提供file_system_type資料結構,在這個資料結構中,含有檔案系統的名 和一個指向其VFS superblock 讀例程的指標。圖9.5顯示出file_system_type資料結構被放進file_system的一個鏈結串列中。 每個 file_system_type 資料結構包含下列信息: Superblock 讀例程 當一個檔案系統的實例被安裝時,該例程被 VFS 調用, 檔案系統名字 這個檔案系統的名字, 例如 ext2 , 設備需要(Device Needed) 這個檔案系統需要一台設備支援嗎?不是所有的檔案系統需要一台設備來支援。例如, /proc 文 件系統, 不要求一個區塊設備, 你可以通過查看/proc/filesystems來獲知系統中什麼檔案系統被登記了。例如: ext2 nodev proc iso9660 9.2.4 安裝一個檔案系統 當超級用戶試圖安裝一個檔案系統時, Linux 核心必須首先驗証在系統調用中被傳遞的參數。盡管 mount 做一些基本的檢查, 它不知道核心中哪些檔案系統是否已經被構建,不知道是否一個安裝點實際上存在。考慮下列安裝命令: $ mount - t iso9660 - o ro /dev/cdrom /mnt/cdrom 本安裝(mount)命令將傳遞給核心3個信息;檔案系統的名字,含有該檔案系統的實體區塊設備和這個新要安裝的檔案系統將被安 裝在現有檔案系統拓樸結構中的什麼地方。 虛擬檔案系統必須做的第一事情是找到該檔案系統。 為了做到這一點,核心瀏覽上節講述的檔案系統鏈結串列,通過遍歷由 file_systems 指向的 file_system_type 資料結構。 如果發現一個匹配的名字,這表明核心目前支援這種檔案系統類型並且得到如何讀取這個檔案系統的 superblock 的例程位址。 如果它不能發現一匹配檔案系統名字,系統核心會查看是否自己被構建為動態地裝載核心模組。( 參見 模組章 )。在這種情況 中核心將請求核心監控程式將相應的檔案系統調入。 下一步,如果指定的實體設備還沒有被安裝, 系統必須發現這個檔案系統的安裝點目錄的 VFS inode。這個 VFS inode 可能已 在核心的inode快取中,或它需要從支援安裝點的檔案系統的區塊設備被讀取進來。一旦 inode 被找到,系統將檢查它是否一個 目錄並且沒有其他的檔案系統已經被安裝在那裡了。同一個目錄不能為多個檔案系統作為安裝點。 然後,VFS 安裝程式碼必須分配一個VFS superblock資料結構並且將相關的安裝信息傳遞給這個檔案系統的superblock讀例程。 系統的所有 VFS superblocks結構被放在 super_blocks向量中。其元素是super_block 資料結構。superblock 讀例程必須基 於它從實體設備讀到的信息填寫 VFS superblock記錄域。對於一個EXT2 檔案系統,這個映射或信息的翻譯的過程是相當容易 的, 它簡單地讀取 EXT2 superblock並且相應填寫 VFS superblock。對於另外的檔案系統,例如MS DOS檔案系統,事情就不 那麼簡單。無論什麼檔案系統,填寫VFS superblock意味著檔案系統必須從支援它的區塊設備讀入一些信息。如果區塊設備 不能被讀或如果它不含有這類檔案系統, 安裝命令將失敗。
圖 9.6 :一個安裝的檔案系統
每個被安裝的檔案系統被一個 vfsmount 資料結構所描述;參見圖 9.6,它們被鏈在一個 vfsmntlist的鏈結串列上。 另外一個指標, vfsmnttail 指向上述鏈結串列的最後入口。mru_vfsmnt 指標指向最近最多使用了的檔案系統。 每個vfsmount結構包含該檔案系統對應的底層設備的設備號,這個檔案系統被安裝的目錄,和一個指標指向其VFS superblock。 如我們已經知道的, VFS superblock 指向這種檔案系統的 file_system_type 資料結構,然後指向這個檔案系統的根 inode。 如果該檔案系統沒有被卸出核心,這個 root inode 一直呆在 VFS inode 緩衝中。 9.2.5 在虛擬檔案系統中尋找一個檔案 為了在虛擬檔案系統中發現一個檔案的VFS inode,VFS必須一次一個目錄地解釋名字,尋找代表名字中間的,那些目錄的各個 VFS inode。逐層找到父目錄的inode是很容易的,因為我們總是可以由其 VFS superblock 得到每個檔案系統的根的VFS inode。 每次當真實的檔案系統探尋一個目錄inode 時,它首先在目錄緩衝中探查這個目錄。如果在目前目錄快取中沒有入口,真實的 檔案系統就從底層的檔案系統或從 inode 快取獲取其 VFS inode 。 9.2.6 在虛擬檔案系統創建一個檔案 9.2.7 (卸掉)Unmounting 一個檔案系統 如果系統還正在使用一個檔案系統的檔案,一個檔案系統是不能被卸下的。例如,你不能umount /mnt/cdrom 如果程序正在使用 它或它的子目錄。如果一個將要被卸下的檔案系統正在被使用,那麼有可能在 VFS inode 快取中存在屬於這個檔案系統的VFS inodes﹔系統的程式碼在核心inodes的鏈結串列中進行尋找這個檔案系統占據的設備擁有的inodes。如果這個安裝的檔案系統的 VFS superblock 是dirty的,這說明它被修改了, 那麼它必須被寫回到在磁碟上的檔案系統中。一旦它被寫回磁碟, VFS superblock 占據的存儲空間就可以被釋放。最後,最後對應於該檔案系統的vfsmount資料結構也被從vfsmntlist 鏈結串列中斷開並且釋放其占據的空間。 9.2.8 VFS Inode 快取(cache) 當一個安裝的檔案系統被瀏覽時,其VFS inodes 不斷地被讀或寫。虛擬檔案系統維持一個 inode 快取以加快檔案系統的存取。 每次一個 VFS inode 從 inode 快取中被讀取,系統就可以節省讀取實體設備的存取時間。 VFS inode 快取的實現是一個其入口是 VFS inodes 鏈結串列指標的一張雜湊表。同一個鏈結串列中的inodes擁有相同的雜湊值。 一個inode的雜湊值的計算是通過其inode的數值和包含其檔案系統的實體設備的辨識器。無論何時虛擬檔案系統存取一個inode 時,它首先查看VFS inode 快取。為了在VFS inode 緩衝中尋找一個inode, 系統首先計算它對應的雜湊值然後將其作為索引值 進入inode 雜湊表。然後通過讀取這個擁有相同雜湊值的inode鏈結串列並逐個比較每個inode的 inode 數字和一樣的 設備辨識器直到發現為止。 如果一個inode在inode快取中被發現,該inode的計數(count)值被增加以顯示出它還有另外的用戶,然後系統接著繼續存取檔案。 否則一個空餘的 VFS inode 必須被發現以便檔案系統能夠從記憶體讀取 inode 。 至於VFS怎麼得到一空餘的inode 有很多選擇。 如果系統可以分配更多的 VFS inodes空間,事情就解決了;它分配一些核心存儲頁並且將它們分成一個個新的, 空餘的inodes並 且把它們放進核心中的 inode 表。系統中所有的 VFS inodes 都在一個被指標first_inode指向的一張鏈結串列中。當然也在那 個雜湊表中。如果系統已經擁有了它可以被允許有的 inodes 的數量,它必須發現一個好的候選inode被重用(resue)。好的候選 inode是一個目前使用計數為0的inodes; 這表示目前系統不再需要這些inode。那些重要的 VFS inodes , 例如檔案系統的根 inodes的使用計數總是比零大,所以從來不會被選中作為重用候選的inode。一旦一個候選inode被選定,它將被清理。 這個 VFS inode 有可能是dirty的,在這種情況中,它需要被寫回到檔案系統。這個inode也可能目前被加鎖了,在這種情況中系統 必須等待直到它被解鎖。VFS inode 必須在重用之前被清理。 當新的 VFS inode 被發現後, 一個特定的檔案系統例程必須被調用,將從底層真實檔案系統讀取來的信息來填充這個已準備好了 的inode資料結構。 當它正在被填寫的過程中,這個新的 VFS inode 的使用計數值為1並且被加鎖,從而其他的實體不能對這個 資料結構進行任何操作直到它已含有完整的資料結構。 為了得到一個實際上需要的 VFS inode, 檔案系統可能需要存取若干個另外的 inodes 。當你讀一個 目錄時,這種情況就會發生;僅僅那個最後的目錄的 inode 是我們所需要得,但是那些中間目錄的 inodes 也必須被讀取。當 VFS inode 快取機制被使用並且被充滿時, 那些較少被使用的 inodes 將被丟棄。較多被使用的 inodes 將在快取中留下。 (譯者注:細心的讀者不難發現,其實在檔案系統中存在許多的機制都是為了克服讀取實體設備帶來 的效率代價。譯者在這裡提出一個問題供大家思考:這些眾多的緩衝機制的缺點是什麼,特別是隨著電腦系統記憶體價格 越來越便宜的時候。這裡有很多的工作和思考可以做。) 9.2.9 目錄快取 為了加快對那些被通常使用的目錄的存取, VFS 維持目錄入口的快取。 當目錄被真實的檔案系統查尋時,它們的細節被加進目錄緩衝。當下一次同樣的目錄被查尋時,例如列目錄或打開在其中的一個 檔案, 系統將在目錄快取中找到其信息。僅僅短的目錄入口 ( 15位元長度) 才被緩衝。這是合理的因為短目錄名字是被最經常 使用的。例如, /usr/X11R6/bin, 當 X 伺服器運行時,該檔案通常被頻繁地被存取。 目錄快取由一張雜湊表組成, 其每個入口指向具有同樣雜湊值的目錄快取的一個鏈結串列。 雜湊函數使用支援該檔案系統的設備的設備標識和目錄名來作為雜湊值的計算□通過雜湊表,可以使得一個目錄項快速的被找到。 一個需要花費很多尋找時間的緩衝機制是沒有意義的。 為了保持一個最新的,正確的緩衝,VFS 維護一些基於LRU(Least Recently Used)演算法的目錄緩衝鏈結串列。當一個目錄項 第一次被放進這個快取時(它第一次被尋找時), 它被增加到第一層 LRU 鏈結串列的鏈尾。在一個已經充滿的快取區情況下, 這將從 LRU 表的前面擠掉一個已經存在的目錄入口項。當這個新目錄項再次被存取時,它被放到第二層 LRU 快取表的鏈尾。 這個行為也可能擠掉一個在第二層 LRU 快取表中鏈頭的一個目錄項。這種在LRU鏈結串列中的鏈頭元素的替換或挪走是很好的 策略。其原因是在鏈頭的元素意味著它們在最近沒有被存取。如果他們有被存取,它們的位置將是靠近鏈結串列的鏈尾。 在第二層 LRU 中的快取資料比在第一層的要安全。這裡的內涵是在第二層的資料不僅僅是被查尋了一下而已,而是被經常地 存取。 9.3 緩衝區快取(Buffer Cache)
圖 9.7 :緩衝區快取
當安裝的檔案系統被使用時,它們產生很多對區塊設備的資料塊的讀和寫請求。所有的塊資料讀和寫請求以buffer_head 資料 結構的形式傳遞給設備驅動程式經由一些標準的核例程調用。這個資料結構裡含有了區塊設備驅動程式所需要的所有信息; 標識一個設備的設備辨識器和要讀取得資料塊的號碼。所有的區塊設備都是具有同樣大小的資料塊的線性組合。為了加快實體 區塊設備的存取, Linux 維持一個塊緩衝區的快取。系統中所有的塊緩衝區都被放在這個緩衝區快取的每個地方, 甚至包括 最新的, 還沒被使用的緩衝區。這個快取被系統中所有的實體區塊設備所共享;在任何一個時間裡,在快取(cache)中都有許多 塊緩衝區(Block Buffer), 它們可能屬於系統中的任何一個區塊設備而且這些資料處於不同的狀態。如果從緩衝區快取中可以 得到有效的資料,這就將節省系統去存取實體設備的時間。任何一個被用來從區塊設備讀取或寫資料的塊緩衝區都進入這個 緩衝區快取(Buffer Cache)。隨著時間的推移,將來它可能從快取被移走以為那些更合適的緩衝區(Buffer),當然如果 它(a Block Buffer)經常被存取,它就可以在快取裡留下。 在快取內的塊緩衝區都通過其對應區塊設備的辨識器合其塊號碼來唯一標識。緩衝區快取由兩個功能部份組成。第一部份是 空餘的塊緩衝區的鏈結串列。對應於每種支援的緩衝區大小,系統中有一個相應的鏈結串列。當系統中的塊緩衝被創建和被 丟棄時,它們就被掛到這些相應的鏈結串列上。目前Linux 系統支援的緩衝區大小是 512 , 1024 , 2048 , 4096 和 8192 位元。第二個功能部份是其快取(cache)本身。這是一張雜湊表。每個入口是指向由指標串起來的緩衝區鏈結串列的 指標。雜湊值索引的計算是有資料塊擁有的設備標識器和塊號碼來產生。圖 9.7 所示是這個雜湊表和幾個入口。塊緩衝區 要麼是在空餘的鏈結串列之中,或在雜湊緩衝區快取中。當他們在緩衝區快取中時,它們也被鏈在 LRU 鏈中。對每種緩衝區 類型都有一張 LRU 鏈結串列。它們被系統用來執行對這種類型緩衝相關的操作。例如,寫緩衝區中的新資料到磁碟中。 緩衝區的類型反映它的狀態。Linux 目前支援下列類型: 乾淨(clean) 閒置的, 新的緩衝區, 鎖(locked) 被鎖的緩衝區, 等待被寫, 臟(dirty) 臟的緩衝區。這些包含新, 有效的資料,將被寫但是到目前為止沒被安排寫到磁碟上去, 分享(shared) 共享的緩衝區, unshared 曾經是共享的緩衝區但是目前不是, 無論何時當一個檔案系統需要從它底層的實體設備讀一個緩衝區(Buffer)時,它試著從緩衝區快取(Buffer cache)得到。如果 它不能從緩衝區快取得到一個緩衝區,然後它將從適當大小的空餘的鏈結串列中得到一個乾淨的(clean)新的緩衝區。這個緩衝 區將被放入將緩衝區快取。如果它需要的緩衝區在緩衝區快取中,它可能已含有最新的資料。如果它不是最新的,或如果它僅 僅是一個新塊緩衝區,檔案系統必須請求設備驅動程式從磁碟讀取適當的資料塊。 像所有的快取一樣,快取必須被高效地維持以便它有效的,公平地為區塊設備分配快取入口。 Linux 使用 bdflush 監控程式 執行這些cache的看護工作。 9.3.1 bdflush 核心監控程式 bdflush 核心監控程序是一個當系統中有太多“dirty☆彽衝區時,提供動態相應的一個簡單的核心監控程序; 含有資料的 緩衝區必須在一定的時間內寫入磁碟。它在系統啟動時間作為一個核心執行緒而運行, 它把自己稱為“ kflushd ”程序。 你如果用 ps 命令在系統中顯示程序列表,你會看到這個名字。大多數情況下,這個監控程序在系統中睡眠直到系統中dirty 的緩衝區的數目變得太大。每次當緩衝區被分配和丟棄時,系統檢查dirty 的緩衝區的數目。如果系統中的緩衝區dirty 的數目超過了一個百分比,bdflush 將被弄醒。預設閥值是 60%。 但是, 如果系統急需緩衝區, bdflush 將被無條件地喚醒。 這個域值可以被觀察和修改,通過update命令。 # update -d bdflush version 1.4 0: 60 Max fraction of LRU list to examine for dirty blocks 1: 500 Max number of dirty blocks to write each time bdflush activated 2: 64 Num of clean buffers to be loaded onto free list by refill_freelist 3: 256 Dirty block threshold for activating bdflush in refill_freelist 4: 15 Percentage of cache to scan for free clusters 5: 3000 Time for data buffers to age before flushing 6: 500 Time for non-data (dir, bitmap, etc) buffers to age before flushing 7: 1884 Time buffer cache load average constant 8: 2 LAV ratio (used to determine threshold for buffer fratricide). 系統中所有的 dirty 緩衝區都被鏈進一個 BUF_DIRTY LRU 鏈結串列中一旦它們變得dirty。bdflush 試著將一定合理數目的 這些資料寫入磁碟。再次強調的是這個數目是可以通過update命令來調節的。其預設值是 500。 9.3.2 更新(update) 程序 update 命令不僅僅是一個命令;它也是一個監控程序。當作為超級用戶運行時 ( 在系統初始化期間 ), 它 周期性地刷新所有舊的dirty的緩衝區到磁碟上。它通過調用一個與bdflush功能差不多的系統服務例程來完成這個任務。 無論何時一個dirty的緩衝區出現時, 系統給它標識上一個它應該被寫入磁碟的系統時間。每次update 運行時,它查看系統中 所有的dirty的緩衝區並將已經到期的刷入磁碟。 9.4 /proc 檔案系統 /proc 檔案系統確實顯示了 Linux 虛擬檔案系統的強大。它其實並不實際存在。/proc 目錄,其子目錄和它的檔案實際上也不 存在。但你如何能 cat /proc/devices 呢? /proc 檔案系統, 就像一個真實的檔案系統一樣,在虛擬檔案系統中登記自己。 然而, 當其下的檔案或目錄被 open 的時候,VFS 對它進行調用請求 inodes 時候, /proc 檔案系統利用核心中的信息來創造 那些檔案和目錄。例如, 核心的 /proc/devices 檔案是從核心中描述設備的資料結構中產生。 /proc 檔案系統提供給一個用戶了解核心內部工作的可讀窗口。一些 Linux 子系統, 例如 Linux 核心模組,在 /proc 檔案系統中都有信息入口項。 9.5 設備特殊檔案 Linux , 像所有的Unix 版本一樣,將硬體設備作為特殊檔案來對待。例如, /dev/null 是空設備。一個設備檔案不占有檔案 系統的任何數據空間, 僅僅是對設備驅動程式的一個存取點。 EXT2 檔案系統和 Linux VFS 都使用特殊類型的 inode 來實現設備檔案。系統中有兩種特殊設備檔案類型;字元和區塊設備檔案。在核心自己內部,設備驅動程式實現檔案的語義: 你能打開他們, 關上他們等等。字元設備允許以字符模式進行所有的I/O操作﹔區塊設備要求I/O操作通過緩衝區快取 (Buffer Cache)的模式。當一個針對設備檔案的 I/O 請求到來時,該請求被提交給相應的設備驅動程式。經常這並不是 系統的一個真正的設備驅動程式,而是一個針對一些子系統的偽設備驅動程式。例如 SCSI 子系統設備驅動層。設備檔案 通過一個主設備號(它標明設備類型),和一個次設備號(主設備類型的一個實例)來標識。例如, 系統的第一個IDE 控制器 上的 IDE 磁碟的主設備號是 3。一個 IDE 磁碟的第一個分區的次設備號是1。因此, ls - l /dev/hda1 將給出: $ brw-rw ---- 1 root 3 ,NOV 24 15:09 /dev/hda1 在核心裡,每台設備都唯一的由一個 kdev_t 資料類型來描述, 這是一個2個位元的整數, 第一個位元包含次設備號﹔第二個 位元包含主設備號。 上述IDE 設備在核心中的資料就是0x0301。一個代表塊或字元設備的 EXT2 inode 在它的第一個直接的塊指標中保持著該 設備的主設備和次設備號。當它被 VFS 讀取時,代表它的 VFS inode 資料結構在其 i_rdev 域中設定上述正確的設備 辨識器信息。