愛伊米

你管這破玩意叫檔案系統?

你手裡有一塊硬碟,大小為 1T

你還有一堆檔案

你管這破玩意叫檔案系統?

這些檔案在硬碟看來,就是一堆二進位制資料而已

你準備把這些檔案儲存在硬碟上,並在需要的時候讀取出來。

要設計怎樣的軟體,才能更方便地在硬碟中讀寫這些檔案呢?

1

首先我不想和複雜的扇區,裝置驅動等細節打交道,因此我先實現了一個簡單的功能,將硬碟按邏輯分成一個個的

,並可以以塊為單位進行讀寫。

每個塊就定義為兩個物理扇區的大小,即 1024 位元組,就是 1KB 啦。

硬碟太大不好分析,我們就假設你的硬碟只有 1MB,那麼這塊硬碟則有 1024 個塊。

OK,我們開始存檔案啦!

準備一個檔案

隨便選個塊放進去,3 號塊吧!

成功!首戰告捷!

2

再存一個檔案!

誒?發現問題了,萬一這個檔案也存到了 3 號塊,不是把原來的檔案覆蓋了麼?不行,得有一個地方記錄,現在可使用的塊有哪些,像這樣。

塊 0:未使用

塊 1:未使用

塊 2:未使用

塊 3:已使用

塊 4:未使用

。。。

塊 1023:未使用

那我們就用 0 號塊,來記錄所有塊的使用情況吧!怎麼記錄呢?

點陣圖!

你管這破玩意叫檔案系統?

那我們給塊 0 起個名字,叫

塊點陣圖

,之後這個塊 0 就專門用來記錄所有塊的使用情況,不再用來存具體檔案了。

當我們再存入一個新檔案時,只需要在塊點陣圖中找到第一個為 0 的位,就可以找到第一個還未被使用的塊,將檔案存入。同時,別忘了把塊點陣圖中的相應位置改成 1。

完美!

3

下面,我們嘗試讀取剛剛的檔案。

咦?又遇到問題了,我怎麼找到剛剛的檔案呢?根據塊號麼?這也太蠢了,就像你去書店找書,店員讓你提供書的編號,而不是書名,顯然不合理。

因此我們給每個檔案起一個名字,叫

檔名

,透過它來尋找這個檔案。

那必然就要有一個地方,記錄檔名與塊號的對應關係,像這樣。

葵花寶典。txt:3 號塊

高量期末複習資料。mp4:5 號塊

中科院物理所的秘密。pdf:10 號塊

。。。

別急,既然都要選一個地方記錄檔名稱了,不妨多記錄一點我們關心的資訊吧,比如檔案大小、檔案建立時間、檔案許可權等。

這些東西自然也要儲存在硬碟上,我們選擇用一個固定大小的空間,來表示這些資訊,多大空間呢?128 位元組吧。

為啥是 128 位元組呢?我樂意。

你管這破玩意叫檔案系統?

我們將這 128 位元組的結構體,叫做一個

inode

之後,我們每存入一個新的檔案,不但要佔用一個塊來存放這個檔案本身,還要佔用一個 inode 來存放檔案的這些

元資訊

,並且這個 inode 的

所在塊號

這個欄位,就指向這個檔案所在的塊號。

如果一個 inode 為 128 位元組,那麼一個塊就可以容納 8 個 inode,我們可以將這些 inode 編上號。

你管這破玩意叫檔案系統?

如果你覺得 inode 數不夠,也可以用兩個或者多個塊來存放 inode 資訊,但這樣用於存放資料的塊就少了,這就看你自己的平衡了。

你管這破玩意叫檔案系統?

同樣,和塊點陣圖管理塊的使用情況一樣,我們也需要一個

inode 點陣圖

,來管理 inode 的使用情況。我們就把 inode 點陣圖,放在 1 號塊吧!

同時,我們把 inode 資訊,放在 2 號塊,一共存 8 條 inode,這樣我們的 2 號塊就叫做

inode 表

現在,我們的檔案系統結構,變成了下面這個樣子。

注意:塊點陣圖是管理可用的塊,每一位代表一個塊的使用與否。inode 點陣圖管理的是一條一條的 inode,並不是 inode 所佔用的塊,比如上圖中有 8 條 inode,則 inode 點陣圖中就有 8 位是管理他們的使用與否。

4

現在,我們的檔案很小,一個塊就能容下。

但如果需要兩個塊、三個塊、四個塊呢?

很簡單,我們只需要採用

連續儲存法

,而 inode 則只記錄檔案的第一個塊,以及後面還需要多少塊,即可。

這種辦法的缺點就是:容易留下大大小小的

空洞

,新的檔案到來以後,難以找到合適的空白塊,空間會被浪費。

你管這破玩意叫檔案系統?

看來這種方式不行,那怎麼辦呢?

既然在 inode 中記錄了檔案所在的塊號,為什麼不擴充套件一下,多記錄幾塊呢?

你管這破玩意叫檔案系統?

原來在 inode 中只記錄了一個塊號,現在擴充套件一下,記錄 8 個塊號!而且這些塊

不需要連續

你管這破玩意叫檔案系統?

嗯,這是個可行的辦法!

但是這也僅僅能表示 8 個塊,能記錄的最大檔案是 8K(記住,一個塊是 1K), 現在的檔案輕鬆就超過這個限制了,這怎麼辦?

很簡單,我們可以讓其中一個塊,作為

間接索引

你管這破玩意叫檔案系統?

這樣瞬間就有 263 個塊(多了 256 -1 個塊)可用了,這種索引叫

一級間接索引

如果還嫌不夠,就再弄一個塊做一級間接索引,或者做二級間接索引(二級間接索引則可以多出 256 * 256 - 1 個塊)。

我們的檔案系統,暫且先只弄一個一級間接索引。硬碟一共才 1024 個塊,一個檔案 263 個塊夠大了。再大了不允許,就這麼任性,愛用不用。

好了,現在我們已經可以儲存很大的檔案了,並且可以透過檔名和檔案大小,將它們準確讀取出來啦!

5

但我們得精益求精,我們再想想看這個檔案系統有什麼毛病。

比如,inode 數量不夠時,我們是怎麼得知的呢?是不是需要在 inode 點陣圖中找,找不到了才知道不夠用了?

同樣,對於塊數量不夠時,也是如此。

要是有個全域性的地方,來記錄這一切,就好了,也方便隨時調整,比如這樣

inode 數量

空閒 inode 數量

塊數量

空閒塊數量

那我們就再佔用一個塊來儲存這些資料吧!由於他們看起來像是站在上帝視角來描述這個檔案系統的,所以我們把它放在最開始的塊上,並把它叫做

超級塊

,現在的佈局如下。

你管這破玩意叫檔案系統?

我們繼續精益求精。

現在,

塊點陣圖

inode 點陣圖

inode 表

,都是是固定地佔據這塊 1、塊 2、塊 3 這三個位置。

假如之後 inode 的數量很多,使得 inode 表或者 inode 點陣圖需要佔據多個塊,怎麼辦?

或者,塊的數量增多(硬碟本身大了,或者每個塊變小了),塊點陣圖需要佔據多個塊,怎麼辦?

程式是死的,你不告訴它哪個塊表示什麼,它可不會自己猜。

很簡單,與超級塊記錄資訊一樣,這些資訊也選擇一個塊來記錄,就不怕了。那我們就選擇緊跟在超級塊後面的 1 號塊來記錄這些資訊吧,並把它稱之為

塊描述符

你管這破玩意叫檔案系統?

當然,這些所在塊號只是記錄起始塊號,塊點陣圖、inode 點陣圖、inode 表分別都可以佔用多個塊。

好了,大功告成!

6

現在,我們再嘗試存入一批檔案。

葵花寶典。txt

高量期末複習資料。mp4

贅婿1。mp4

贅婿2。mp4

贅婿3。mp4

贅婿4。mp4

中科院物理所的秘密。pdf

誒?這看著好不爽,所有的檔案都是平鋪開的,能不能擁有

層級關係

呢?比如這樣

葵花寶典。txt

高量期末複習資料。mp4

贅婿

贅婿1。mp4

贅婿2。mp4

贅婿3。mp4

贅婿4。mp4

中科院物理所的秘密。pdf

我們將葵花寶典。txt 這種稱為

普通檔案

,將贅婿這種稱為

目錄檔案

,如果要訪問贅婿1。mp4,那全檔名要寫成

贅婿/贅婿1。mp4。

如何做到這一點呢?那我們又得把 inode 結構拿出來說事了。

你管這破玩意叫檔案系統?

此時需要一個屬性來區分這個檔案是普通檔案,還是目錄檔案。

缺什麼就補什麼嘛,我們已經很熟悉了,專門加一個 4 位元組,來表示

檔案型別

你管這破玩意叫檔案系統?

如果是

普通檔案

,則這個 inode 所指向的資料塊仍然和之前一樣,就是檔案本身原封不動的內容。

但如果是

目錄檔案

,則這個 inode 所指向的資料塊,就需要重新規劃了。

這個資料塊裡應該是什麼樣子呢?可以是一個一個指向不同 inode 的緊挨著的結構體,比如這樣。

你管這破玩意叫檔案系統?

這樣先透過

贅婿

這個目錄檔案,找到所在的資料塊。再根據這個資料塊裡的一個個帶有

inode

資訊的結構體,找到這個目錄下的所有檔案。

完美!

7

不過這樣的話,你想想看,如果想要檢視一下贅婿

這個目錄下的所有檔案

(比如 ll 命令),將檔名和檔案型別都展示出來,怎麼辦呢?

就需要把一個個結構體指向的 inode 從 inode 表中取出,再把檔名和檔案型別取出,這很是浪費時間。

而讓使用者看到一個目錄下的所有檔案,又是一個極其常見的操作。

所以,不如把檔名和檔案型別這種常見的資訊,放在資料塊中的結構體裡吧。

你管這破玩意叫檔案系統?

同時,inode 結構中的檔名,好像就沒啥用了,這種變長的東西放在這種定長的結構中本身就很討厭,早就想給它去掉了。而且還能給其他資訊省下空間,比如檔案所在塊的陣列,就能再多幾個了。

太好了,去掉它!

你管這破玩意叫檔案系統?

OK,大功告成,現在我們就可以給檔案分門別類放進不同目錄下了,還可以在目錄下建立目錄,無限套娃!

8

現在的檔案系統,已經比較完善了,只是還有一點不太爽。

我們訪問到一個目錄下,可以很舒服地看到目錄裡的檔案,然後再根據名稱訪問這個目錄下的檔案或者目錄,整個過程都是一個套路。

但是,最上層的目錄下的所有檔案,即

根目錄

,現在仍然需要透過遍歷所有的 inode 來獲得,能不能和上面的套路統一呢?

答案非常簡單,我們規定,

inode 表中的 0 號 inode,就表示根目錄

,一切的訪問,就從這個根目錄開始!

你管這破玩意叫檔案系統?

好了,這回沒有然後了!

我們最後來欣賞下我們的檔案系統架構。

你管這破玩意叫檔案系統?

你是不是覺得這沒啥了不起的。

但這個破玩意,它就叫檔案系統

完~

編輯:Eric