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

淺析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)

分享創造快樂