【摘要】如何把資料存放在存放裝置上?又如何訪問這些資料?這是檔案系統必須回答的兩個問題。現代檔案系統種類繁多,良莠不齊。這些檔案系統各有什麼特徵?有什麼優缺點?適用的環境是什嗎?本文將詳細介紹基於Linux系統的三個主要檔案系統:ext2、ext3和ReiserFS。
檔案系統是解決如何在存放裝置上儲存資料的一套方法,包括儲存布局、檔案命名、空間管理、安全控制等。Linux作業系統支援很多現代的流行檔案系統,其中ext2、ext3和ReiserFS最普遍。ext2檔案系統是伴隨著linux一起發展起來的,在ex2的基礎上增加日誌就是ext3,這兩個檔案系統可以很容易的轉換而不必重新格式化儲存介質,它們是linux特有的。ReiserFS可以說是後起之秀了,最初它不是用於linux,所以對linux來說它是一個泊來品。ReiserFS採用了一個非常先進的新穎演算法,最新的4版本真正做到了檔案系統操作的原子性(類似資料庫事務操作的原子性),據官方報道,ReiserFS“原子性”演算法優於現代資料庫的“原子性”演算法,做到了空間和時間複雜度的雙優!一個檔案系統能做到這個份上,我算是徹底服了:-)。
現代Linux系統繼續採用了早期(1992年前)發展的虛擬檔案系統(Virtual File System,簡寫為VFS)理念,VFS是一個介於使用者和實際檔案系統之間,為使用者提供了一個統一的編程介面,儘管處於其之下的各種檔案系統類型千差萬別,但對終端使用者來說卻是一樣的。例如當使用者張三輸入命令cd /data後,他並沒有意識到自己剛從ext3檔案系統進入ReiserFS檔案系統,他仍然使用命令ls –l列出目前的目錄下的所有檔案,而且顯示格式也是一樣,但是幕後英雄VFS可忙壞了,它不得不啟動一個演算法找到ReiserFS檔案系統提供的介面函數並調用它們,要知道ReiserFS提供的一套函數可不同於ext3的那一套。得益於VFS,其他檔案系統可以採用“熱插拔”的非常簡便的方式加入或退出Linux作業系統,例如當第一次mount一個檔案系統A時,相應地就把該檔案系統對應的模組裝載到核心(假設沒有被直接編譯進核心),當最後把檔案系統A對應的裝置umount時,對應的模組被卸載出去。
LINUX的檔案系統可以追溯到八十年代末的Minix檔案系統,而Minix檔案系統具有幾個明顯的缺點:檔案系統不能超過64M,目錄只能存放固定數目的檔案,檔案名稱長度不能超過14個字元,檔案尺寸小於64M。之後由於繼續沿襲傳統技術,儘管linux的標準檔案系統依次經曆了VFS(1992年前)、ext(1992年)、ext2(1993年)和最新的ext3這一系列檔案系統的傳種接代,但“基因”沒變,只不過新一代都是改進前一代的不足,或者加入一些新東東而已。但由於Linux幾乎在一開始就引入VFS的概念(我個人認為非常英明^O^),Linux對其他第三方檔案系統都是包容的,目前幾乎所有先進的檔案系統都支援,其中著名的ReiserFS已經成了Novell的SuSe
Linux發行版的預設檔案系統,但也由於IT界最臭名昭著的四字經“向後相容”的要求,今日各種linux發行版中存在過多地包容早已經落伍的檔案系統的現象,比如Minix、FAT等,但對於一個富有理論和經驗的系統管理員來說,所有的這些“累贅”都可以在彈指間一一化解。
下面我們先看看一塊物理硬碟是如何分區的。三個主要的參數是柱面數、磁頭數和每磁軌扇區數,起始編號分別為0、0和1,0柱面0磁頭1扇區是主引導分區,上面存放引導代碼和四個主要磁碟分割表(如果一個物理硬碟多於4個,那麼就放在擴充分區),0柱面0磁頭上的其他扇區保留,真正的分區是從0柱面1磁頭1扇區開始的。在linux中,用/dev/had、/dev/hdb、/dev/sda、/dev/sdc等表示一個物理磁碟。實驗:
- 查看硬碟物理參數:hdparm /dev/sda; hdparm –i /dev/had(IDE硬碟);
- 讀入分區表資訊:dd if=/dev/sda of=/tmp/mbr bs=1 count=64 skip=446;
- 查看主要磁碟分割表資訊:od –t x1 mar;
- 備份主引導區資訊:dd of=/dev/sda if=/dev/sda bs=512 count=1 seek=1;
自從鄧小平南巡講話那年之前VFS投胎於linux以來(Mr. Linus不愧為一個有遠見的接生婆,@_@),VFS就一直與Linux形影不離,並且成了Kernel的一部分,在Kernel版本號碼如芝麻開花般節節攀升的同時自己也枝繁葉茂起來。
VFS就像一個一個默默無聞的公僕,它介於各種檔案系統和使用者進程之間(參見圖〖一〗),一方面屏蔽下層的各種異構檔案系統的個性,另一方面為上層使用者提供一個統一的介面(如open、read等),同時VFS還提供一些檔案系統沒有的操作,比如,沒有哪個檔案系統提供了函數lseek,此函數由VFS實現。
Kernel中存在一個全域指標變數file_systems,該變數指向一個元素類型為file_system_type的鏈表,當mount一個檔案系統時裝載對應的模組,而裝載模組時觸發的行為register_filesystem()會產生一個file_system_type結構並把它掛接到file_systems鏈表上,也就是說所有的已經mount的檔案系統都掛在這個鏈表上,file_system_tpe結構中有一個指向超級塊結構的指標,儲存介質上的超級塊在裝置mount時被讀入記憶體,直到umount時從記憶體中刪除。
EXT2是linux上標準的檔案系統,EXT3是在EXT2基礎上增加日誌形成的,其思想還是可以追溯到早期UNIX家族發展的基於超級塊和inode的經典概念。/dev/sda#n表示/dev/sda硬碟上的第#n個分區。
分區上的扇區是從0開始編號的,每個扇區512bytes,一個塊(block)大小一般是1k、2k、3k和4k,具體大小可在建立檔案系統時指定,如果不指定塊大小那麼會根據分區的大小自動相應選擇一個。分區開始的1024bytes存放引導程式boot,接下來的1024bytes存放超級塊super block,組描述字group descriptors起始於一個新塊,並單獨佔用一個塊空間,之後的所有塊被組織成塊組,塊組才是真正存放檔案的場所。超級塊含有整個檔案系統的一些全域參數,如:卷名、通用唯一識別碼、狀態、塊大小、總塊數、每組inode數,總i節點數、每組塊數等等,super
block在檔案mount時被讀入記憶體,直到umount時被釋放,由於超級塊對於檔案系統來說至關重要,所以超級塊一般在第1、3、5、7和9組的首塊中存有副本。
- 建立一個ext2檔案系統:mke2fs –c –c –L “Test Filesystem” /dev/sda2;
- 查看ext2分區開始部分的資訊:od –t x1 /dev/sda2 | more;其中“aa55”之前的為boot,含有魔數“ef53”的地區為super block;
- 查看超級塊中的內容:tune2fs –l /dev/sda2;
- 查看詳細的塊組資訊:dumpe2fs –x /dev/sda2;
一個塊組描述字佔用32個位元組,其中三個主要指標分別指到到這個塊組的i節點表、i節點位元影像和塊位元影像。塊組的設計是為了拉近inode和它的資料區塊的距離,這樣就可以提高磁碟存取效能,一個塊組的具體結構見圖〖二〗右邊部分。
inode是EXT2檔案系統的精華,一個inode對應一個檔案,inode編號是全域性的,從1開始,描述參考圖〖三〗。
inode中存放檔案的一些重要屬性,如許可權、檔案大小、訪問時間、修改時間、建立時間、檔案屬主ID、組ID、塊數等。Inode包含15個指標,前12個直接指向資料區塊,後三個依次是一次間接、二次間接和三次間接指向資料區塊。檔案系統的目錄不同於普通檔案的結構,是一種固定格式的檔案,裡面的每一個條目代表目錄中的一個檔案。
在ext2檔案系統上增加一個特殊的inode(記錄檔),用於記錄檔案系統中繼資料的變化,即日誌journal,這就是EXT3檔案系統。Ext3這種粗糙的實現日誌的文法付出了很大的代價:寫兩次!
- ext2和ext3檔案系統之間的轉換(不需要重新格式化)
- ext2轉換成ext3檔案系統:tune2fs –j /dev/sda2;如果sda之前已經mount,那麼該命令執行完後在頂層目錄建立了一個不能刪除和dump的記錄檔.journal,機器重啟或umount且e2fsck後該檔案將被改變成隱藏的特殊記錄檔inode。如果/dev/sda2是啟動時自動mount的,那麼還需手工修改/etc/fstab中/dev/sda2所對應的檔案系統類型,否則還是按ext2類型mount和使用。
- ext3轉換成ext2檔案系統:umount /dev/sda2; tune2fs –O ^has_journal /dev/sda2; e2fsck –y /dev/sda2; mount –t ext2 /dev/sda2 /mnt; 對於自動mount的裝置還需修改/etc/fstab。