歡迎光臨
每天分享高質量文章

淺析Linux檔案系統

一、檔案系統層次分析

由上而下主要分為用戶層、VFS層、檔案系統層、快取層、塊設備層、磁盤驅動層、磁盤物理層

用戶層

最上面用戶層就是我們日常使用的各種程式,需要的接口主要是檔案的創建、刪除、打開、關閉、寫、讀等。

VFS層

我們知道Linux分為用戶態和內核態,用戶態請求硬體資源需要呼叫System Call通過內核態去實現。用戶的這些檔案相關操作都有對應的System Call函式接口,接口呼叫VFS對應的函式。

檔案系統層

不同的檔案系統實現了VFS的這些函式,通過指標註冊到VFS裡面。所以,用戶的操作通過VFS轉到各種檔案系統。檔案系統把檔案讀寫命令轉化為對磁盤LBA的操作,起了一個翻譯和磁盤管理的作用。

快取層

檔案系統底下有快取,Page Cache,加速性能。對磁盤LBA的寫資料快取到這裡。

塊設備層

塊設備接口Block Device是用來訪問磁盤LBA的層級,讀寫命令組合之後插入到命令佇列,磁盤的驅動從佇列讀命令執行。Linux設計了電梯演算法等對很多LBA的讀寫進行優化排序,儘量把連續地址放在一起。

磁盤驅動層

磁盤的驅動程式把對LBA的讀寫命令轉化為各自的協議,比如變成ATA命令,SCSI命令,或者是自己硬體可以識別的自定義命令,發送給磁盤控制器。Host Based SSD甚至在塊設備層和磁盤驅動層實現了FTL,變成對Flash芯片的操作。

磁盤物理層

讀寫物理資料到磁盤介質。

二、檔案系統結構與工作原理

我們都知道,windows檔案系統主要有fat、ntfs等,而linux檔案系統則種類繁多,主要有VFS做了一個軟體抽象層,向上提供檔案操作接口,向下提供標準接口供不同檔案系統對接,下麵主要就以EXT4檔案系統為例,講解檔案系統結構與工作原理:

上面兩個圖大體呈現了ext4檔案系統的結構,從中也相信能夠初步的領悟到檔案系統讀寫的邏輯過程。下麵對上圖裡邊的構成元素做個簡單的講解:

引導塊

為磁盤分割槽的第一個塊,記錄檔案系統分割槽的一些信息,引導加載當前分割槽的程式和資料被儲存在這個塊中。一般占用2KB。

超級塊

超級塊用於儲存檔案系統全域性的配置引數(譬如:塊大小,總的塊數和inode數)和動態信息(譬如:當前空閑塊數和inode數),其處於檔案系統開始位置的1k處,所占大小為1k。

為了系統的健壯性,最初每個塊組都有超級塊和組描述符表(以下將用GDT)的一個拷貝,但是當檔案系統很大時,這樣浪費了很多塊(尤其是GDT占用的塊多),後來採用了一種稀疏的方式來儲存這些拷貝,只有塊組號是3, 5 ,7的冪的塊組(譬如說1,3,5,7,9,25,49…)才備份這個拷貝。

通常情況下,只有主拷貝(第0塊塊組)的超級塊信息被檔案系統使用,其它拷貝只有在主拷貝被破壞的情況下才使用。

塊組描述符

GDT用於儲存塊組描述符,其占用一個或者多個資料塊,具體取決於檔案系統的大小。

它主要包含塊位圖,inode位圖和inode表位置,當前空閑塊數,inode數以及使用的目錄數(用於平衡各個塊組目錄數),具體定義可以參見ext3_fs.h檔案中struct ext3_group_desc。

每個塊組都對應這樣一個描述符,目前該結構占用32個位元組,因此對於塊大小為4k的檔案系統來說,每個塊可以儲存128個塊組描述符。由於GDT對於定位檔案系統的元資料非常重要,因此和超級塊一樣,也對其進行了備份。GDT在每個塊組(如果有備份)中內容都是一樣的,其所占塊數也是相同的。

從上面的介紹可以看出塊組中的元資料譬如塊位圖,inode位圖,inode表其位置不是固定的,當然預設情況下,檔案系統在創建時其位置在每個塊組中都是一樣的,如圖2所示(假設按照稀疏方式儲存,且n不是3,5,7的冪)

塊組

每個塊組包含一個塊位圖塊,一個 inode 位圖塊,一個或多個塊用於描述 inode 表和用於儲存檔案資料的資料塊,除此之外,還有可能包含超級塊和所有塊組描述符表(取決於塊組號和檔案系統創建時使用的引數)。下麵將對這些元資料作一些簡要介紹。

塊位圖

塊位圖用於描述該塊組所管理的塊的分配狀態。如果某個塊對應的位未置位,那麼代表該塊未分配,可以用於儲存資料;否則,代表該塊已經用於儲存資料或者該塊不能夠使用(譬如該塊物理上不存在)。由於塊位圖僅占一個塊,因此這也就決定了塊組的大小。

Inode位圖

Inode位圖用於描述該塊組所管理的inode的分配狀態。我們知道inode是用於描述檔案的元資料,每個inode對應檔案系統中唯一的一個號,如果inode位圖中相應位置位,那麼代表該inode已經分配出去;否則可以使用。由於其僅占用一個塊,因此這也限制了一個塊組中所能夠使用的最大inode數量。

Inode表

Inode表用於儲存inode信息。它占用一個或多個塊(為了有效的利用空間,多個inode儲存在一個塊中),其大小取決於檔案系統創建時的引數,由於inode位圖的限制,決定了其最大所占用的空間。

以上這幾個構成元素所處的磁盤塊成為檔案系統的元資料塊,剩餘的部分則用來儲存真正的檔案內容,稱為資料塊,而資料塊其實也包含資料和目錄。

瞭解了檔案系統的結構後,接下來我們來看看操作系統是如何讀取一個檔案的:

大體過程如下:
1、根據檔案所在目錄的inode信息,找到目錄檔案對應資料塊
2、根據檔案名從資料塊中找到對應的inode節點信息
3、從檔案inode節點信息中找到檔案內容所在資料塊塊號
4、讀取資料塊內容

到這裡,相信很多人會有一個疑問,我們知道一個檔案只有一個Inode節點來存放它的屬性信息,那麼你可能會想如果一個大檔案,那它的block一定是多個的,且可能不連續的,那麼inode怎麼來表示呢,下麵的圖告訴你答案:

也就是說,如果檔案內容太大,對應資料塊數量過多,inode節點本身提供的儲存空間不夠,會使用其他的間接資料塊來儲存資料塊位置信息,最多可以有三級尋址結構。

到這裡,應該都已經非常清楚檔案讀取的過程了,那麼下麵再丟擲兩個疑問:
1、檔案的拷貝、剪切的底層過程是怎樣的?
2、軟連接和硬連接分別是如何實現的?

下麵來結合stat命令動手操作一下,便知真相:
1)拷貝檔案:創建一個新的inode節點,並且拷貝資料塊內容

2)剪切檔案:同個分割槽裡邊mv,inode節點不變,只是更新目錄檔案對應資料塊裡邊的檔案名和inode對應關係;跨分割槽mv,則跟拷貝一個道理,需要創建新的inode,因為inode節點不同分割槽是不能共享的。

3)軟連接:創建軟連接會創建一個新的inode節點,其對應資料塊內容儲存所鏈接的檔案名信息,這樣原檔案即便刪除了,重新建立一個同名的檔案,軟連接依然能夠生效。

4)硬鏈接:創建硬鏈接,並不會新建inode節點,只是links加1,還有再目錄檔案對應資料塊上增加一條檔案名和inode對應關係記錄;只有將硬鏈接和原檔案都刪除之後,檔案才會真正刪除,即links為0才真正刪除。

赞(0)

分享創造快樂