Linux 檔案系統相關的基本概念

sparkdev發表於2019-07-18

本文介紹 Linux 檔案系統相關的基本概念。

硬碟的物理組成

碟片
硬碟其實是由單個或多個圓形的碟片組成的,按照碟片能夠容納的資料量,分為單盤(一個硬碟裡面只有一個碟片)或多盤(一個硬碟裡面有多個碟片)的硬碟。下面是一張碟片的示意圖(此圖來自網際網路):

磁軌和柱面
硬碟中有磁頭在碟片上讀寫資料,磁頭固定在機械臂上,機械臂上有多個磁頭(每個碟片的兩側各一個)。當磁頭固定不動時(假設機械手臂不動),碟片轉一圈所畫出來的圓就是磁軌(track)。所有碟片上相同半徑的那個磁軌就組成了柱面(cylinder)。柱面是磁碟分割槽是的最小單位。

扇區
由圓心向外畫直線,可以將磁軌再劃分為扇區,扇區就是碟片上最小的讀寫單位。通常情況下,一個扇區的大小為 512 個位元組。因此可以使用下面的公式計算磁碟的容量:
柱面數 * 磁頭數 * 扇區數 * 512 位元組

磁碟分割槽

為什麼要對硬碟進行分割槽呢?
因為我們必須要告訴作業系統:這塊硬碟可以訪問的區域是從 A 柱面到 B 柱面。如此一來,作業系統才能控制硬碟磁頭去 A-B 範圍內的柱面上訪問資料。如果沒有告訴作業系統這些資訊,它就無法在磁碟上存取資料。所以對磁碟分割槽的要點是:記錄每一個分割槽的起始與結束柱面
實際上,分割槽時指定的開始和結束位置是柱面上的扇區(sector):

下圖是透過 fdisk 命令檢視到的磁碟分割槽資訊:

那麼,這些分割槽的資訊(起始柱面與結束柱面)被存放在了哪裡呢?答案是磁碟的主引導區(Master Boot Recorder, MBR)。MBR 在一塊硬碟的第 0 軌上,這也是計算機啟動之後要去使用硬碟時必須讀取的第一個區域。 這個區域內記錄了硬碟裡所有分割槽的資訊即磁碟分割槽表,以及啟動時可以寫入載入程式的位置。因此 MBR 對於硬碟來說至關重要,如果它壞掉了,這塊磁碟也就壽終正寢了。下面是磁碟分割槽表的示意圖(此圖來自網際網路):

檔案系統

在告知系統分割槽所在的起始與結束柱面後,需要將分割槽格式化為作業系統能夠識別的檔案系統。每個作業系統能夠識別的檔案系統並不相同,比如 Windows 系統在預設的情況下就無法識別 Linux 的檔案系統,所以要針對作業系統來格式化分割槽。可以簡單的認為每個分割槽就是一個檔案系統。

邏輯塊
不論哪種檔案系統,目的都是為了儲存資料。前面提到,硬碟的最小讀寫單位是扇區,而現實中資料的讀寫單位並不是扇區的大小,原因是使用扇區的大小為單位來讀寫資料的效率實在是太低了。因為一個扇區只有 512 個位元組,而磁頭是一個扇區一個扇區的讀取資料,也就是說,如果檔案有 10M,那麼讀取這個檔案磁頭就要進行 20480 次讀取操作(I/O)。
為了提升效率,就有了邏輯塊(Block)的概念。邏輯塊是在分割槽進行檔案系統的格式化時所指定的"最小儲存單位",這個最小儲存單位以扇區的大小為基礎(因為扇區為硬碟的最小物理儲存單位),大小為扇區大小的 2ⁿ 倍。此時,磁頭一次可以讀取一個邏輯塊。指定邏輯塊的大小為 4KB(即由連續的 8 個扇區構成的一個塊),那麼,同樣讀取一個 10M 的檔案,磁頭要讀取的次數則大幅下降為 2560 次,這樣就大大提高了檔案的讀取效率。
需要注意的是,邏輯塊也並不是越大越好。因為一個邏輯塊最多僅能容納一個檔案(這裡指 Linux 的 ext2 檔案系統)。這有什麼問題呢?舉例來說,假如邏輯塊的大小為 4KB,有一個檔案大小為 0.1KB,這個小檔案將佔用掉一個塊的空間。也就是說,該塊雖然可以容納 4KB 的容量,然而由於檔案只佔用了 0.1KB,實際上剩下的 3.9KB 空間就不能再被使用了(完全浪費掉了)。所以好的方式是根據實際的使用場景來設定邏輯塊的大小。

在分割槽上建立檔案系統時,可以指定檔案系統的邏輯塊大小:

上面命令中我們指定的邏輯塊大小為 1024 B,也就是兩個扇區的大小。我們還可以透過 tune2fs 檢視現有檔案系統邏輯塊的大小:

這裡需要區分三個概念:
扇區、邏輯塊和頁
塊裝置中最小的定址單元是扇區。
邏輯塊是檔案系統的一種抽象--只能基於塊來訪問檔案系統。核心執行的所有磁碟操作都是按照塊進行的(但是所有裝置的 I/O 必須以扇區為單位進行操作)。對塊的要求有:必須是扇區大小的 2 的整數倍;不能超過頁的大小。
核心把記憶體的物理頁作為記憶體的管理單位,因為從磁碟讀取的資料最終都會被儲存在記憶體中,所以系統最佳化的結果是不允許檔案系統中的邏輯塊超過記憶體頁的大小。可以透過下面的命令檢視系統中頁的大小:

$ getconf PAGESIZE

超級塊
分割槽完成後,每個分割槽會被格式化為一個檔案系統。而每個檔案系統開始位置的那個塊就稱為超級塊(superblock)。超級塊會記錄整個檔案系統的整體資訊,包括 inode 與 block 的總量、使用量、剩餘量等。
也就是說,要使用一個分割槽(或檔案系統)來進行資料訪問時,第一個要經過的就是超級塊。所以,如果超級塊損壞了,這個分割槽上的資料也就丟掉了。

inode
Linux 作業系統的檔案資料除了檔案實際內容外,通常含有非常多的屬性,例如檔案許可權(rwx)與檔案屬性(擁有者、群組、時間引數等)。檔案系統通常會將這兩部份的資料分別存放在不同的區塊,許可權與屬性放置到 inode 中,至於實際資料則放置到 datablock 區塊中。

block
實際記錄檔案的內容,若檔案太大時,會佔用多個 block。

每個檔案都會佔用一個 inode,inode 內則有檔案資料放置的 block 號碼。下面是 inode、block 資料存取的示意圖(此圖來自網際網路):

這種資料存取的方法我們稱為索引式檔案系統(indexed allocation)。

掛載點
在 Linux 系統中,檔案系統被安裝在一個特定的掛載點(一個普通的目錄)上,所有的已安裝檔案系統都作為根檔案系統樹的枝葉出現在系統中。與這種單一、統一的樹形成鮮明對照的就是 Windows 系統的表現,它們以字母命名檔案系統,比如我們常見的 C 盤、D 盤。

參考:
《鳥哥的私房菜》

相關文章