覺得自己寫得比較好的一次操作系統作業,而且可能對大家在Linux的使用中有幫助,所以貼上來。。
GNU/Linux用戶都知道,在*nix業界有一句話叫做“一切皆文件”,這是對Linux文件系統的一個很好抽象,正規地,Linux的文件系統可以認為包括4種主要組成部分:名字空間(給事物取名,並按一種層次解構組織他們的形式)、API(用來便利和操作對象的一套系統調用)、安全模型(用來保護,隱藏何共享事物的方案)、實現(把邏輯模型同實際硬件聯系到一起的軟件)
Linux定義了一個抽象的內核級接口,能夠容許集中不同的後端文件系統,文件樹的有些部分由傳統的給予磁盤的實現來處理,其他部分則由內核中單獨的驅動程序來負責。我們說“Linux中一切皆文件”直觀地可以這樣理解:所有的東西,設備、內存都模擬成文件,我們可以把他分成5種文件類型,c 字符設備、b 塊設備、l 連接、f 普通文件、d 目錄。而Windows中,我們則可以極端地認為“一切皆設備”,所有文件都使用inode文件索引,inode文件索引是Linux文件系統的一大特色,利弊都很明顯,inode設計方便程序使用,能夠提供各種功能的實現,但是同時inode本身也成為了一種限制(比如inode用完了就算還有物理空間都不能再使用了),但是我們在使用mke2fs格式化文件系統的時候,可以通過參數-i來指定目標邏輯分區的inode數量,說到mke2fs就必然說到linux傳統的兩種文件格式——ext2跟ext3,ext3跟ext2文件格式的不同,就是在於ext3是在ext2文件格式上加入了日值系統,於是我們可以想到,我們可以不必改變文件格式的基礎結構,在這兩種方式間互相切換,我們可以很簡單地使用mke2fs -j /dev/hda*來為ext2開啟日志使之成ext3文件系統(反之,我們也可以通過關閉日志把它當作一個ext2文件系統來使用。),Linux的靈活性還體現在我們甚至可以通過-J device=""來指定日志文件的存放位置,也就是說,我們可以把/dev/hda1的日志文件放在/dev/hda2上,ext3日志文件大小介於1024到102400個文件系統塊之間,在使用mke2fs -j格式化完成一個文件系統之後,我們可以通過df -h /dev/hda*整個命令來查看被格式化硬盤的狀況,我們可以看到約有1%的空間被使用掉了。這就是為日志文件開辟的區域!
在發生文件系統操作的時候,所要求的修改首先寫入日志,在完成日志更新之後,寫入一條“提交記錄(commit record)”標記日志項的結束。只有這樣以後,才對正規的文件系統做修改,如果發生了崩潰,可以用日志記錄重構出完全相同的文件系統,除了ext3文件系統,還有一種叫做ReiserFS的文件系統也被廣泛地應用,它也是一種日志文件系統,但是這種文件系統沒有針對系統(比如服務器)進行優化,可能會碰到大量的同時讀寫現象。除了日志功能之外,Reiser還提供了一種模塊化的文件系統接口,能讓軟件開發人員和系統管理員在非常細的粒度上指定應該怎樣處理和保護文件。
下面再詳細地講一下ext2跟ext3文件系統,ext2文件系統由5個部分構成,一組索引結點(inode)存儲單元,一組分散的“超級塊(superblock)”,一組文件系統中磁盤塊的映射表。一份磁盤塊使用情況的匯總,最後是數據塊。每個文件系統都被分成若干個塊簇,諸如inode表這樣的結構在塊簇之間進行分配,於是,要一起訪問的若干磁盤塊可以在硬盤上彼此保存得很靠近。這種成簇機制減少了在訪問同一個文件時需要搜索整個硬盤的情況,縮影結點是長度固定的表項,每個索引結點都保存著一個文件的信息,因為在Linxu初始化文件系統的結構時,必須開辟出一塊空間用來保存索引結點。也就是我前面說過的mke2fs -i來指定inode數量,但是一般情況下我們默認即可,superblock是一個描述文件系統特性的記錄。它包括的信息有:磁盤塊的長度,索引結點表的大小和位置,磁盤塊的映射表和使用信息,塊簇大小,以及其他幾個重要的文件系統的參數,因為superblock的如此重要,所以損壞超級塊會對文件系統造成很嚴重的後果,因此在硬盤上的分散位置(在每個塊簇的起始處)保存有它的幾個副本。Linux為每個已經安裝的文件系統在內存中保存有一個超級塊的副本,又在硬盤上保存了幾個副本,系統調用sync把被緩存的超級塊flush到它們硬盤上的永久位置上,瞬間就讓文件系統保持了一致性。sync也會flush已經修改過的索引結點和被緩存的數據塊,我們可以通過update命令啟動守護進程bdflush,它每30s執行一次sync調用,將每次崩潰,比如斷電造成的數據損失降到最低。(我們都知道,Linux為了提高性能,一定程度上緩和磁盤讀寫速度瓶頸,采用了系統內存做磁盤緩存,一旦斷電,緩存中的數據將無法及時寫入磁盤,造成損失。)文件系統的磁盤塊映射表是它所包含的自由塊的一張表。在寫心文件的時候,就要檢查這個映射表,設計一種有效的布局方案。塊的使用情況匯總記錄了已經投入使用的塊的基本信息。
而之前說過的ext3跟ext2文件系統最大的不同就是它的日志文件,ext3的sync每5秒執行一次同步操作,在選擇日志模式方面,我們還可以在性能和功能之間有三種權衡的選擇:默認ordered模式保證文件系統始終保持一致性,writeback模式在系統崩潰後會產生受損文件,但在某些情況下運行速度更快,journal模式使用的日志文件最大,一定程度上會降低系統重啟時回復文件系統的速度,但是在對於數據庫應用時速度更快。ext3文件系統的模式是用/etc/fstab文件中的data=mode選項來設置的,可以是上面三者之一。下面提一下swap,跟windows的虛擬頁面文件相似,是在磁盤上虛擬出一塊超慢的ram。我們可以通過mkswap /dev/hda*來創建swap區,並且通過使用swapon /dev/hda*來啟用swap。
最後來講一下Linux文件系統的檢查跟修復。系統在發生內核時空或者電源失效的任何時候,都可能在朋虧之前給處於活動狀態的文件系統引入少量的不一致性,因為內核對數據塊和匯總信息進行了緩沖,所以該文件系統最近的影響在硬盤和內存之間進行了分攤,在系統崩潰的過程中,映象的那訊部分丟失了,內存中被緩沖的塊都被那些最近才保存到硬盤上的數據有效地“覆蓋”了,於是造成數據損壞,解決這個問題有兩個途徑,小損壞可以使用fsck(filesystem consisitency check意思是文件一致性檢查)命令來修復。前面已經說過,比如ext3這樣的日志文件系統將元數據寫出到一個連續的日志文件中,在命令返回之前日志文件才被緩沖到硬盤上,元數據最終會從日志中移至它在文件系統中的固定位置去。如果系統崩潰了,那麼日志就可以返回到最近一次保持一致性的地方,,不要求對文件系統進行完全的交叉檢查。在引導系統的時候,也要運行fsck,以確保文件系統處於一致狀態,但是它的運行速度比檢查傳統的ext2文件系統要快得多。在具有大型文件系統的系統中,整個功能可以幫助節省很多啟動時間。最常見的損壞類型有5種,未被引用的索引結點,超大的連接數目,沒有記錄在磁盤塊映射表中的空閒數據塊,列出的空閒數據塊還在某個文件中使用,超級塊中的匯總信息不正確。fsck能夠安全和自動修復這5類問題。在修復過程中,如果fsck找到一個無法確定其父目錄的文件,那麼它會把該文件放到lost+found目錄中,因為一個文件的名稱只被記錄在該文件的父目錄中,所以孤兒文件的名字是不能被使用的,所以仿制在lost+found中的文件將用他們的inode號來命名。最後提一下,對於非常重要的數據,fsck對於非上面5類錯誤可能造成更大的不可挽回的損失,所以我們應該使用dump轉存儲硬盤,或者用dd整個文件系統。