1、文件系統結構
為了改善I/O效率,內存和磁盤之間的I/O轉移是以塊為單位的,而不是以字節為單位,每塊分為一個或多個扇區,根據磁盤驅動器的不同,扇區從32-4096B不等,通常為512B。
為了提供對磁盤的高效和便捷的訪問,操作系統通過文件系統來輕松存儲、定位、提取數據。
文件系統本身通常由許多不同的層組成。從上到下依次是:應用程序->邏輯文件系統->文件組織系統->基本文件系統->I/O控制->設備
設計中每層利用較低層的功能來創建新的功能來對更高層來服務。
I/O控制為最底層,由設備驅動程序和中斷處理程序組成,實現內存與磁盤之間的信息傳輸,實質就是通過一些命令來控制磁盤的指針來訪問磁盤上的數據。
基本文件系統只需要向合適的設備驅動程序發送一般命令就可以對磁盤上的物理塊進行讀寫,每個塊由其數值磁盤地址來標識。
文件組織模塊知道文件及其邏輯塊和物理塊,由於知道所使用的文件分配類型和文件位置,文件組織模塊可以將邏輯塊地址轉換成基本文件系統所使用的物理塊地址。
邏輯文件系統管理元數據,元數據包括文件西游的所有結構數據,而不包括實際數據,邏輯文件系統根據給定符號文件名來管理目錄結構,並提供給文件組織模塊所需要的信息。
采用分層的結構實現文件系統,能夠最大限度的減小重復的代碼。
2、文件系統實現
2.1、分區與安裝
磁盤布局因為操作系統而異,一個磁盤可以分成多個分區,或者一個卷可以橫跨多個磁盤上的數個分區。
“生”磁盤是指沒有合適文件系統的磁盤空間。
引導信息能保存在各個分區,它由自己的格式,因為在引導系統時系統並沒有文件系統設備驅動程序,所以並不能解釋文件系統格式。
根分區包括操作系統內核和其他系統文件,在引導時裝入內存,其他卷根據不同操作系統可以再引導時自動裝入或在此后手動裝入。
2.2、虛擬文件系統
絕大多數操作系統都是通過面向對象技術來簡化、組織和模塊化實現過程,使用這些方法允許不同文件系統類型可以通過同樣的結構來實現,這也包括網絡文件,采用數據結構和子程序,可以分開基本系統調用和實現細節,因此,文件系統,主要分為三個層次:從上到下依次是文件系統接口->VFS接口->本地文件系統。
第二層VFS為虛擬文件系統,主要由兩個作用:
1)VFS層通過定義一個清晰的VFS接口,以將文件系統的通用接口操作和具體實現分開。多個VFS接口的實現可以共存在同一台機器,它允許訪問已裝在本地的多個類型的文件。
2)VFS提供了在網絡上唯一標識一個文件的機制。
VFS能區分本地文件和遠程文件,根據文件系統類型來進一步區分不同本地文件。
VFS根據文件系統類型調用特定文件類型操作以處理本地請求,通過調用NFS協議程序來處理遠程請求。
3、目錄實現
目錄分配和目錄管理算法的選擇對文件系統的效率、性能和可靠性有很大的影響。
3.1、線性列表
最為簡單的目錄實現算法就是使用存儲文件名和數據塊指針的線性列表,這種方法編程簡單但是運行時較為費時。
要創建新文件,必須首先搜索目錄以確定沒有同樣名稱的文件存在,接着,在目錄后增加一個新條目,要刪除文件時,根據給定文件名搜索目錄,接着釋放分配給他的空間,如果需要重用目錄條目,可以有許多辦法,可以將目錄條目標記為不再使用或者可以將它加到空閑目錄條目上。
3.2、哈希表
用於文件目錄的另一個數據結構就是哈希表,采用這種方法時,處理使用線性列表存儲目錄條目外,還使用了哈希數據結構。哈希表根據文件名得到一個值,並返回一個指向線性列表中元素的指針,因此,它大大減小了目錄搜索時間。
哈希表的最大困難就是其通常固定的大小和哈希函數對大小的依賴性。
4、分配方法
4.1、連續分配
連續分配方法要求每個文件在磁盤上占有一組連續的塊。
一個文件的目錄條目包括開始塊的地址和該文件所分配的區域的長度。對於一個連續分撇文件的訪問很容易,要順序訪問,文件系統會記住上次訪問過塊的磁盤地址,如需要可讀入下一塊,因此,連續分配支持順序訪問和直接訪問。
連續分配也存在一些問題:很難為新文件找到空間。也就是從一個空閑孔列表中尋找一個滿足大小為n的空間,從一組空閑孔中尋找一個空閑孔最為常用的策略是首次適用和最優適用,這兩種策略在空間使用方面不相上下,但是首次適合運行更快。
連續分配的另外一個問題是確定一個文件需要多少空間,我們在保存之后很可能要增加或刪除文件內容,那么保存在空間大小就很難確定。為了解決這個問題,有的操作系統使用修正的連續分配,該方案分配一塊連續的空間,當空間不夠時,另一塊被稱為擴展的連續空間會添加到原來的分配中,這樣,文件塊的位置就成為能夠為開始地址、塊數、加上一個指向下一個擴展的指針,如此,解決文件大小問題。
4.2、鏈接分配
鏈接分配解決了連續分配的所有問題,采用鏈接分配,每個文件時磁盤塊的鏈表,磁盤塊分布在磁盤的任何地方。
要創建一個新文件,可以簡單的在目錄中增加一個新條目,對於鏈接分配,每個目錄條目都有一個指向文件首塊的指針。要寫文件就會通過空閑空間管理系統找到一個空閑塊,然后這個新塊就會被寫入並鏈接到文件的尾部,要讀文件,可以通過塊到塊的指針,簡單的讀塊。
鏈接分配也存在問題,首先,鏈接分配不支持文件的直接訪問。
鏈接分配的另一個缺點是指針需要空間,存在空間浪費,解決這個問題,我們需要盡可能的降低指針所占空間。所以我們常用的解決方法是將多個塊組成簇,按照簇而不是按照塊來分配。
鏈接分配的另一個問題是可靠性,假設我們文件中的一個指針丟失,那么該指針之后的內容也相應丟失,可靠性差。
一種鏈接分配方法的變種是文件分配表。目錄條目包含文件首塊的塊號碼,根據塊號碼索引的FAT條目包含文件下一塊的塊號碼,這種鏈接會一直存在下去,直到最后一塊。
4.3、索引分配
鏈接分配解決了連續分配的外部碎片和大小聲明問題,但是,如果不使用FAT,那么鏈接分配還是不支持世界訪問,因此,我們提出索引分配,索引分配通過把所有的指針放到一起,通過索引塊解決問題。
每個文件都有其索引塊,這是一個磁盤塊地址的數組。
當創建文件時,索引塊的所有指針都是空,當首次寫入第i塊時,先從空閑空間管理器中得到一塊,再將其地址寫到索引塊的第i個條目。
索引分配支持直接訪問,且沒有外部碎片問題,但是索引分配會浪費空間,索引塊指針的開銷通常比鏈接分配指針的開銷大。所以我們需要盡可能的降低索引塊的大小,主要有下面幾種方案:
鏈接方案:一個索引塊通常為一個磁盤塊,為了處理大文件,可以將多個索引塊鏈接起來。
多層索引:鏈接表示的一種變種是用第一層索引塊指向一組第二層索引塊,第二層索引塊再指向文件塊。
組合方案:在UFS中使用的另一種方案是將索引塊的十五個指針存在文件的inode中,,這其中前12個指針指向直接塊,它們包含了能存儲文件數據的塊的地址,因此,小文件不需要其他的索引塊,但是如果塊大小為4KB,那么不超過48KB的文件可以直接訪問,其他三個指針指向間接塊,第一個間接塊指針為一級間接塊的地址,一級間接塊為索引塊,它包含的不是數據,而是那些包含數據塊的地址。
5、空閑空間管理
為了記錄空閑磁盤空間,系統需要維護一個空閑空間鏈表,空閑空間鏈表記錄了所有空閑磁盤空間
5.1、位向量
空閑空間表實現為位圖或者位向量,每塊用一位表示,如果一塊為空閑,那么其位為“1”,如果一塊已分配,那么其位為“0”
這種方法的主要優點是查找磁盤上第一個空閑塊和n個連續空閑塊時相對簡單和高效
5.2、鏈表
空閑空間的另一種方法是將所有空閑磁盤塊用鏈表鏈接起來,並將其指向第一空閑塊的指針保存在磁盤的特殊位置上,同時也緩存在內存中,不過這種方法的效率不高,要遍歷整個表時,需要讀入每一塊,這就需要大量的I/O空間,好在遍歷整個表並不是一個經常操作。
5.3、組
對空閑鏈表的一個改進是將n個空閑塊的地址存在第一個空閑塊中,這些塊中的前n-1個確實為空,而最后一塊包含另外n個空閑塊的地址。
5.4、計數
記錄第一塊的地址和緊跟第一塊的連續的空閑塊的數量n,這樣,空閑空間表的每個條目包括磁盤地址和數量。
