磁盤是用來儲文件的,但是必須先把磁盤格式化為某種格式的文件系統,才能存儲文件。文件系統的目的就是組織和管理磁盤中的文件。在 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文件系統簡單剖析(一)