Linux EXT2 檔案系統

sparkdev發表於2019-07-22

磁碟是用來儲檔案的,但是必須先把磁碟格式化為某種格式的檔案系統,才能儲存檔案。檔案系統的目的就是組織和管理磁碟中的檔案。在 Linux 系統中,最長見的是 ext2 系列的檔案系統。其早期版本為 ext2,後來又發展出 ext3 和 ext4。ext3 和 ext4 雖然對 ext2 進行了增強,但是其核心設計並沒有發生變化,所以我們仍是以較老的 ext2 作為演示物件。

基本結構

Ext2 檔案系統在格式化的時候一般會包含多個區塊群組(blockgroup)。Ext2 格式化後有點像下面這樣:

這是因為檔案系統非常大時,如果將所有的 inode 和所有的 block 放在一起管理起來會比較麻煩。所以將檔案系統分割為多個 Block Group,每個 Block Group 中都有獨立的 inode/block/superblock 系統。

Block
Block 就是我們在《Linux 檔案系統相關的基本概念》一文中介紹的邏輯塊。對於 ext2 檔案系統來說,硬碟分割槽首先被分割為一個一個的邏輯塊(Block),每個 Block 就是實際用來儲存資料的單元,大小相同,Block 按照0,1,2,3 的順序進行編號,第一個 Block 的編號為 0。ext2 檔案系統支援的 Block 的大小有 1024 位元組、2048 位元組和 4096 位元組,Block 的大小在建立檔案系統的時候可以透過引數指定,如果不指定,則會從 /etc/mke2fs.conf 檔案中讀取對應的值。原則上,Block 的大小與數量在格式化後就不能夠發生改變了,每個 Block 內最多隻會存放一個檔案的資料(即不會出現兩個檔案的資料被放入同一個 Block 的情況),如果檔案大小超過了一個 Block 的 size,則會佔用多個 Block 來存放檔案,如果檔案小於一個 Block 的 size,則這個 Block 剩餘的空間就浪費掉了。
可以使用 dumpe2fs 命令檢視 Block 的大小:

$ sudo dumpe2fs /dev/sda1 | grep "Block size:"

在筆者的環境中,輸出的結果如下:
Block size:               1024

注意,Ext2 檔案系統的 block 主要有下面一些特點:

  • block 的大小與數量在格式化完就不能夠再改變了(除非重新格式化)
  • 每個 block 內最多隻能夠放置一個檔案的資料
  • 如果檔案大於 block 的大小,則一個檔案會佔用多個 block 數量
  • 若檔案小於 block,則該 block 的剩餘容量就不能夠再被使用了

Block Group
Block 在邏輯上被劃分為多個 Block Group,每個 Block Group 包含的 Block 數量相同,具體是在 SuperBlock 中透過 s_block_per_group 屬性定義的(最後一個 Block Group 除外,最後剩下的 Block 數量可能小於 s_block_per_group,這些 Block 會被劃分到最後一個 Block Group 中)。dumpe2fs 命令會列出所有的 Block Group 資訊,但是在統計資訊中卻沒有說明當前的檔案系統中包含有多少個 Block Group。下面是 dumpe2fs 輸出的 Block Group 資訊的節選:

...
Group 0: (Blocks 1-8192) [ITABLE_ZEROED]
  Checksum 0xa22b, unused inodes 501
  Primary superblock at 1, Group descriptors at 2-81
  Reserved GDT blocks at 82-337
  Block bitmap at 338 (+337), Inode bitmap at 354 (+353)
  Inode table at 370-497 (+369)
  5761 free blocks, 501 free inodes, 2 directories, 501 unused inodes
  Free blocks: 2432-8192
  Free inodes: 12-512
Group 1: (Blocks 8193-16384) [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
  Checksum 0xea71, unused inodes 512
  Backup superblock at 8193, Group descriptors at 8194-8273
  Reserved GDT blocks at 8274-8529
  Block bitmap at 339 (bg #0 + 338), Inode bitmap at 355 (bg #0 + 354)
  Inode table at 498-625 (bg #0 + 497)
  7855 free blocks, 512 free inodes, 0 directories, 512 unused inodes
  Free blocks: 8530-16384
  Free inodes: 513-1024
...

Group0 佔用從 1 到 8192 號的 block。其中的 Superblock 則在 1 號 block 內。
檔案系統描述說明(Group descriptors)佔用從 2 到 81 號 block。
Block bitmap 和 Inode bitmap 分別在 338 和 354 號 block 上。
Inode table 佔用 370-497 號 block。
Group0 當前可用的 block 號為:2432-8192,可用的 inode 號碼為:12-512。
Group 內 inode 數的計算方式:
一個 inode 佔用 256 Bytes
Inode 佔用的 block 數:497 - 370 + 1 = 128
每個 block 的大小為 1024 Bytes
Inode 數為:128 * 1024 / 256 = 512

Boot Block
每個磁碟分割槽的開頭 1024 位元組大小都預留為分割槽的啟動扇區,存放載入程式和資料,所以又叫引導塊。引導塊在第一個 Block,即 Block 0 中存放,但是未必佔滿這個 Block,原因是 Block 的大小可能大於 1024 位元組。
這裡是存放開機管理程式的地方,這是個非常重要的設計。因為這樣使得我們能夠把不同的開機管理程式安裝到每個檔案系統的最前端,而不用覆蓋整顆磁碟唯一的 MBR,這樣就能支援多系統啟動了。

Block Group 的組成部分

如上圖所示,每個 Block Group 都由下面幾個組成部分:

  • Superblock(超級塊)
  • Group Description(組描述)
  • Block bitmap(塊點陣圖)
  • Inode bitmap(inode 點陣圖)
  • Inode table(inode 表)
  • Data Blocks(資料塊)

Superblock(超級區塊)
Superblock 是記錄整個 filesystem 相關資訊的地方,其實上除了第一個 block group 內會含有 superblock 之外,後續的 block group 不一定都包含 superblock,如果包含,也是做為第一個 block group 內 superblock 的備份。superblock 記錄的主要資訊有:

  • block 與 inode 的總量
  • 未使用與已使用的 inode/block 數量
  • block 與 inode 的大小(block 為 1,2,4K,inode 為 128 Bytes 或 256 Bytes)
  • filesystem 的掛載時間、最近一次寫入資料的時間、最近一次檢驗磁碟(fsck)的時間等檔案系統的相關資訊
  • 一個 valid bit 數值,若此檔案系統已被掛載,則 valid bit 為 0,若未被掛載,則 valid bit 為 1

Superblock 的大小為 1024 Bytes,它非常重要,因為分割槽上重要的資訊都在上面。如果 Superblock 掛掉了,分割槽上的資料就很難恢復了。可以使用 dumpe2fs 命令檢視 分割槽的 Superblock 資訊,如果新增選項 -h,dumpe2fs 命令則只輸出 Superblock 中的資訊:

$ sudo dumpe2fs -h /dev/sdd1

Group Description(組描述)
Group Description 用來描述每個 group 的開始與結束位置的 block 號碼,以及說明每個塊(superblock、bitmap、inodemap、datablock) 分別介於哪一個 block 號碼之間。

Block bitmap(區塊對照表)
在建立檔案時需要為檔案分配 block,屆時就會選擇分配空閒的 block 給檔案使用。如何檢視 block 是否已經被使用了呢?此時就需要藉助於 block bitmap 了。透過 block bitmap 可以知道哪些 block 是空的,因此係統就能夠很快地找到空閒空間來分配給檔案。同樣的,在刪除某些檔案時,檔案原本佔用的 block 號碼就要釋放出來,此時在 block bitmap 當中相對應到該 block 號碼的標誌就需要修改成"空閒"。這就是 block bitmap 的作用。

Inode bitmap(inode 對照表)
inode bitmap 與 block bitmap 的功能類似,只是 block bitmap 記錄的是使用與未使用的 block 號,而 inode bitmap 則記錄的是使用與未使用的 inode 號。

Inode table    
Inode table 中存放著一個個 inode,inode 的內容記錄檔案的屬性以及該檔案實際資料是放置在哪些 block 內,inode 記錄的主要的檔案屬性如下:

  • 該檔案的讀寫許可權(rwx)
  • 該檔案的擁有者和所屬組(owner/group)
  • 該檔案的容量
  • 該檔案的 ctime(建立時間)
  • 該檔案的 atime(最近一次的讀取時間)
  • 該檔案的 mtime(最近修改的時間)
  • 該檔案的特殊標識,比如 SetUID 等
  • 該檔案真正內容的指向(pointer)

inode 的數量與大小也是在格式化時就已經固定了的,另外 inode 還有如下特點:

  • 每個 inode 大小均固定為 128 Bytes(新的 ext4 為 256 Bytes)
  • 每個檔案都僅會佔用一個 inode
  • 檔案系統能夠建立的檔案數量與 inode 的數量相關
  • 系統讀取檔案時需要先找到 inode,並分析 inode 所記錄的許可權與使用者是否符合,若符合才能夠開始讀取 block 的內容

Data block
Data block 是用來存放檔案內容的地方,Ext2 檔案系統 1K、2K 和 4K 大小的 block。在格式化檔案系統時 block 的大小就確定了,並且每個 block 都有編號。需要注意的是,由於 block 大小的差異,會導致檔案系統能夠支援的最大磁碟容量和最大單個檔案的大小並不相同。下表描述了 block 大小與檔案系統以及單個檔案大小的關係:

此外 Ext2 檔案系統的 block 還有下面一些限制:

  • block 的大小與數量在格式化後就不能再改變了(除非重新格式化)
  • 每個 block 內最多隻能夠放置一個檔案的資料
  • 如果檔案大於 block 的大小,那麼一個檔案會佔用多個 block
  • 若檔案小於 block,則該 block 的剩餘容量也不能再被使用了(磁碟空間被浪費)

參考:
鳥哥的私房菜
dumpe2fs man page
Linux ext2, ext3, ext4 檔案系統解讀[1]
Ext2檔案系統簡單剖析(一)

相關文章