1. 程式人生 > >Linux 磁碟分割槽和檔案系統

Linux 磁碟分割槽和檔案系統

本文以Ext2檔案系統為例講述Linux檔案系統,由於Ext3檔案系統是直接從Ext2檔案系統發展而來,它完全相容Ext2檔案系統,所以本文的內容對於Ext2和Ext3都是適用的。

我們首先看一下磁碟分割槽和檔案系統的結構圖:

 

圖 1 磁碟分割槽和檔案系統結構圖

整個磁碟可以分為1個MBR(Master Boot Record)和4個partitions。其中MBR的結構示意圖如圖2所示

圖 2 MBR示意圖

一個partition由兩部分組成:Boot Sector和File System。Boot Sector大小是1KB,這是有PC標準規定的,用來儲存磁碟分割槽資訊和啟動資訊,任何File System都不能使用Boot Sector。

下面進入正題,詳細介紹File System——檔案系統。檔案系統中儲存的最小單位是塊(Block),一個塊究竟多大是在格式化時確定的,例如mke2fs的-b選項可以設定塊大小為1024、2048或4096位元組。Ext2檔案系統將整個分區劃成若干個同樣大小的塊組(Block Group),如圖1所示,每個塊組都由以下部分組成:

1.         Super Block(超級塊)

描述整個分割槽的檔案系統資訊,例如塊大小、檔案系統版本號、上次mount的時間等等。超級塊在每個塊組的開頭都有一份拷貝。

在Linux原始碼中,Super Block對應的結構體如圖3:

 

圖 3 ext3_super_block結構體

超級塊包含以下重要資訊:

1)         Magic Number

對於Ext2和Ext3檔案系統來說,這個欄位的值應該正好等於0xEF53。如果不等的話,那麼這個硬碟分割槽上肯定不是一個正常的Ext2或Ext3檔案系統。從這裡,我們也可以估計到,Ext2和Ext3的相容性一定是很強的,不然的話,Linux核心的開發者應該會為Ext3檔案系統另選一個Magic Number才對。

2)         Mount Count and Maximum Mount Count

每次mount此檔案系統,Mount Count都會加1,當它等於Maximum Mount Count時系統將發出警告:maxumal mount count reached, running e2fsck is recommended。

3)         Block Group Number

Block Group的個數。

4)         Block Size

該檔案系統在建立(格式化)時指定的block大小,如1024 Bytes。

5)         Blocks per Group

每個Block Group中block的個數,檔案系統在建立時指定。

6)         Free Blocks

檔案系統中空閒塊數。

7)         Free Inodes

檔案系統中空閒Inode數。

8)         First Inode

檔案系統中第一個inode號。EXT2根檔案系統中第一個inode將是指向'/'目錄的目錄入口。

2.         GDT(Group Descriptor Table,塊組描述符表)

由很多塊組描述符組成,整個分割槽分成多少個塊組就對應有多少個塊組描述符。每個塊組描述符(Group Descriptor)儲存一個塊組的描述資訊,例如在這個塊組中從哪裡開始是inode表,從哪裡開始是資料塊,空閒的inode和資料塊還有多少個等等。和超級塊類似,塊組描 述符表在每個塊組的開頭也都有一份拷貝,這些資訊是非常重要的,一旦超級塊意外損壞就會丟失整個分割槽的資料,一旦塊組描述符意外損壞就會丟失整個塊組的資料,因此它們都有多份拷貝。通常核心只用到第0個塊組中的拷貝,當執行e2fsck檢查檔案系統一致性時,第0個塊組中的超級塊和塊組描述符表就會拷貝到其它塊組,這樣當第0個塊組的開頭意外損壞時就可以用其它拷貝來恢復,從而減少損失。

在Linux原始碼中,GDT對應的結構體如圖4:

圖 4 ext3_group_desc結構體

GDT包含以下重要資訊:

1)         Blocks Bitmap

對應此資料塊組的塊分配點陣圖的塊號。在塊分配和回收時使用。

2)         Inode Bitmap

對應此資料塊組的inode分配點陣圖的塊號。在inode分配和回收時使用。

3)         Inode Table

對應資料塊組的inode表的起始塊號。每個inode用下面5中介紹的ext3_inode結構來表示。

4)         Free blocks count, Free Inodes count, Used directory count

分別代表空閒的block數、空閒的inode數和使用的directory數。

3.         Block Bitmap(塊點陣圖)

一個塊組中的塊是這樣利用的:資料塊儲存所有檔案的資料,比如某個分割槽的塊大小是1024位元組,某個檔案是2049位元組,那麼就需要三個資料塊來存,即使第三個塊只存了一個位元組也需要佔用一個整塊;超級塊、塊組描述符表、塊點陣圖、inode點陣圖、inode表這幾部分儲存該塊組的描述資訊。那麼如何知道哪些塊已經用來儲存檔案資料或其它描述資訊,哪些塊仍然空閒可用呢?塊點陣圖就是用來描述整個塊組中哪些塊已用哪些塊空閒的,它本身佔一個塊,其中的每個bit 代表本塊組中的一個塊,這個bit為1表示該塊已用,這個bit為0表示該塊空閒可用。

為什麼用df命令統計整個磁碟的已用空間非常快呢?因為只需要檢視每個塊組的塊點陣圖即可,而不需要搜遍整個分割槽。相反,用du命令檢視一個較大目錄的已用空間就非常慢,因為不可避免地要搜遍整個目錄的所有檔案。

與此相聯絡的另一個問題是:在格式化一個分割槽時究竟會劃出多少個塊組呢?主要的限制在於塊點陣圖本身必須只佔一個塊。用mke2fs格式化時預設塊大小是1024位元組,可以用-b引數指定塊大小,現在設塊大小指定為b位元組,那麼一個塊可以有8b個bit,這樣大小的一個塊點陣圖就可以表示8b個塊的佔用情況,因此一個塊組最多可以有8b個塊,如果整個分割槽有s個塊,那麼就可以有s/(8b)個塊組。格式化時可以用-g引數指定一個塊組有多少個塊,但是通常不需要手動指定,mke2fs工具會計算出最優的數值。

4.         inode Bitmap(inode點陣圖)

和塊點陣圖類似,本身佔一個塊,其中每個bit表示一個inode是否空閒可用。

5.         inode Table(inode表)

我們知道,一個檔案除了資料需要儲存之外,一些描述資訊也需要儲存,例如檔案型別(常規、目錄、符號連結等),許可權,檔案大小,建立/修改/訪問時間等,也就是ls -l命令看到的那些資訊,這些資訊存在inode中而不是資料塊中。每個檔案都有一個inode,一個塊組中的所有inode組成了inode表。

inode表佔多少個塊在格式化時就要決定並寫入塊組描述符中,mke2fs格式化工具的預設策略是一個塊組有多少個8KB就分配多少個inode。由於資料塊佔了整個塊組的絕大部分,也可以近似認為資料塊有多少個8KB就分配多少 個inode,換句話說,如果平均每個檔案的大小是8KB,當分割槽存滿的時候inode表會得到比較充分的利用,資料塊也不浪費。如果這個分割槽存的都是很 大的檔案(比如電影),則資料塊用完的時候inode會有一些浪費,如果這個分割槽存的都是很小的檔案(比如原始碼),則有可能資料塊還沒用完inode就 已經用完了,資料塊可能有很大的浪費。如果使用者在格式化時能夠對這個分割槽以後要儲存的檔案大小做一個預測,也可以用mke2fs的-i引數手動指定每多少個位元組分配一個inode。

EXT2 inode還可以描敘特殊裝置檔案。雖然它們不是真正的檔案, 但可以通過它們訪問裝置。所有那些位於/dev中的裝置檔案可用來存取Linux裝置。例如mount程式可把裝置檔案作為引數。

在Linux原始碼中,GDT對應的結構體如圖5:

圖 5 ext3_inode結構體

inode包含以下重要資訊:

1)         Mode

它包含兩類資訊;inode描敘的內容以及使用者使用許可權。EXT2中的inode可以表示一個檔案、目錄、符號連線、塊裝置、字元裝置或FIFO。

2)         Owner Information

表示此檔案或目錄所有者的使用者和組標誌符。檔案系統根據它可以進行正確的存取。

3)         Size

以位元組計算的檔案尺寸。

4)         Timestamps

inode建立及最後一次被修改的時間。

5)         Datablocks Pointers

指向此inode描敘的包含資料的塊指標。前12個指標指向包含由inode描敘的物理塊, 最後三個指標包含多級間接指標。例如兩級間接指標指向一塊指標,而這些指標又指向一些資料塊。這意味著訪問檔案尺寸小於或等於12個數據塊的檔案將比訪問大檔案快得多。這種定址方式如圖6所示,詳細解釋如下:我們看到在inode裡面可以存放 EXT3_N_BLOCKS(= 15)這麼多個 block 指標。使用者資料就從這些 block 裡面獲得。15個blocks不一定放得下全部的使用者資料,在這裡 ext3 檔案系統採取了一種分層的結構。這組15個block指標的前12個是所謂的direct blocks,裡面直接存放的就是使用者資料。第13個block,也就是所謂的indirect block,裡面存放的全部是block指標,這些block指標指向的block才被用來存放使用者資料。第 14個block 是所謂的double indirect block,裡面存放的全是block指標,這些block指標指向的block也被全部用來存放 block 指標,而這些 block 指標指向的 block,才被用來存放使用者資料。第 15個block是所謂的triple indirect block,比上面說的double indirect block有多了一層 block指標。

圖 6 資料塊定址方式

6.         Data Block(資料塊)

根據不同的檔案型別有以下幾種情況

1)         對於常規檔案,檔案的資料儲存在資料塊中。

2)         對於目錄,該目錄下的所有檔名和目錄名儲存在資料塊中,注意檔名儲存在它所在目錄的資料塊中,除檔名之外,ls -l命令看到的其它資訊都儲存在該檔案的inode中。注意這個概念:目錄也是一種檔案,是一種特殊型別的檔案。

3)         對於符號連結,如果目標路徑名較短則直接儲存在inode中以便更快地查詢,如果目標路徑名較長則分配一個數據塊來儲存。

4)         裝置檔案、FIFO和socket等特殊檔案沒有資料塊,裝置檔案的主裝置號和次裝置號儲存在inode中。