存儲系統科普——文件系統介紹


簡介

該篇blog只是存儲系列科普文章中的第二篇,所有文章請參考:

博客所有文章

在工程架構領域里,存儲是一個非常重要的方向,這個方向從底至上,我分成了如下幾個層次來介紹:

  1. 硬件層:講解磁盤,SSD,SAS, NAS, RAID等硬件層的基本原理,以及其為操作系統提供的存儲界面;
  2. 操作系統層:即文件系統,操作系統如何將各個硬件管理並對上提供更高層次接口;
  3. 單機引擎層:常見存儲系統對應單機引擎原理大概介紹,利用文件系統接口提供更高級別的存儲系統接口;
  4. 分布式層:如何將多個單機引擎組合成一個分布式存儲系統;
  5. 查詢層:用戶典型的查詢語義表達以及解析;

文件系統磁盤分配

在存儲知識棧上提到文件系統, 大家首先就關心他是如何管理好硬件層提供的磁盤空間的。

本文開篇就先描述典型的幾種文件系統管理磁盤的技術方案: 連續分配, 鏈式分配, 索引分配。

連續分配

顧名思義, 就是創建文件的時候, 給分配一組連續的塊。在單獨拿出一塊地方存儲各個文件的meta信息, meta信息也很簡單, 包含文件名, 起始位置和長度即可, 這個存放meta信息的地方也叫做FAT(文檔分配表)。

如下圖:

連續分配示意圖

該方案的優點:

  1. 簡便, 適用於一次性寫入操作;
  2. 所需磁盤尋道次數和尋道時間最少;

缺點也很明顯:

  1. 文件不能動態增長, 因為后面的塊可能已經分配給別人了;
  2. 不利於文件的插入和刪除, 插入文件之前需要聲明文件大小;
  3. 外部碎片問題;

為了克服連續分配的問題, 又進化出來了鏈式分配方案。

鏈式分配

鏈式分配即將文件塊像鏈表一樣管理起來, 每個塊中放一個指針, 指針指向下一個文件塊所在的位置。這樣在FAT中存儲也很簡單, 只需要存儲文件名, 起始塊號和結束塊號(都可以不存)。

如下圖:

鏈式分配示意圖

該方案的優點:

  1. 提高磁盤利用率, 沒有碎片問題
  2. 有利於文件的插入, 刪除

缺點:

  1. 存取速度慢, 需要移動的磁道次數多, 尋道時間長;
  2. 讀寫任何一個地方都需要沿着指針前進直到找到對應塊為止;
  3. 鏈接占據了一定的磁盤空間, 數據不是嚴格按照塊大小分配;

索引分配

這是一個折衷方案, 也是現在大部分文件系統采用的方案, 他綜合了連續分配和鏈式分配的好處。

該方案會在FAT中保存所有文件塊的位置, 各文件系統都有一套自己對應的細節分配策略, 會保證一個文件盡量連續的同時, 又避免出現大量的磁盤碎片。

如下圖:

索引分配示意圖

該方案的優點是:

  1. 能夠保持好大部分文件的局部性
  2. 滿足文件插入, 刪除的高效
  3. 隨機讀寫不需要沿着指針前進

缺點:

  1. 會有較多的磁盤尋道次數
  2. 索引表本身管理復雜, 也會帶來額外的系統開銷

ext文件系統

基本概念

  1. 塊. 即Block, 數據存儲的最小單元, 每個塊都有一個唯一的地址, 從0開始, 起源於第一個可以用來存儲數據的扇區;
  2. 超級塊. 超級塊保存了各種文件系統的meta信息, 比如塊大小信息。他位於文件系統的2號和3號扇區(物理地址), 占用兩個扇區大小;
  3. 塊組. 所有的塊會划分成多個塊組, 每個塊組包含同樣多個塊, 但是可能整個文件系統整個塊數不是塊組的整數倍, 所以最后一個塊組包含的個數可能會小於其他塊;

總體結構

一個ext文件系統分成多個塊組, 每個塊組的結構基本相同, 如下:

塊組架構圖

解釋如下:

  1. 0~1號扇區: 引導扇區. 如果沒有引導代碼, 則這兩個扇區為空, 全部用0填充;

  2. 2~3號扇區: 超級塊, 超級塊包含各種meta信息:

    1. 塊大小, 每個塊組包含塊數, 總塊數, 第一個塊前保留塊數, inode節點數, 每個塊組的inode節點數
    2. 卷名, 最后掛載時間, 掛載路徑, 文件系統是否干凈, 是否要調用一致性檢查標識
    3. 空間inode節點和空閑塊的記錄信息, 在分配inode節點和新塊的時候使用
  3. 組描述符表:

    位於超級塊后面的一個塊, 注意在超級塊之前只占用了4個扇區, 如果一個塊大小超過4個扇區的話, 這里就會有空的扇區。

    組描述符表中包含了所有塊組的描述信息, 每個塊組占據32個字節(差不多是8個整數的大小)。如果格式化使用默認參數, 那么組描述符表不會超過一塊塊組。

    組描述符和超級塊在每個塊組中都有一個備份, 但是激活了稀疏超級塊特征的情況除外。

    稀疏超級塊即不是在所有塊組中都存儲超級塊和組描述符的備份, 默認該策略被激活, 其策略類似當塊組號是3,5,7的冪的塊組才存副本。

  4. 塊位圖表

    每個塊對應一個bit, 只包含了本塊組的信息。而文件系統創建的時候, 默認每個塊組包含的塊數跟每個塊包含的bit數是一樣的, 這種情況下每個塊位圖表正好等於一個塊的大小。

    而該位圖表的塊的起始位置會在組描述符表中指定, 大小則為塊組中包含塊數個bit。

  5. inode位圖塊

    跟塊位圖表類似, 通常情況他也只占用一個塊。通常一個塊組中的inode節點數會小於block數量, 所以其不會超過一個塊大小。

  6. inode節點表

    每個inode都占用128位的一個描述信息, 起始位置在組描述符中表示, 大小為inode節點數*128。

  7. 數據區

    這就是真正存儲數據的區域。

塊大小為4096的時候, 各部分和扇區對應關系如下圖:

4096塊圖

塊大小為2048的時候, 各部分和扇區對應關系如下圖:

2048塊圖

超級塊詳細信息

超級塊總是位於文件系統的第1024~2048字節處。

超級塊中包含的信息如下:

偏移(16進制) 字節數 含義&解釋
00~03 4 文件系統中總inode節點數
04~07 4 文件系統中總塊數
08~0B 4 為文件系統預保留的塊數
0C~0F 4 空閑塊數
10~13 4 空間inode節點數
14~17 4 0號塊組起始塊號
18~1B 4 塊大小(1024左移位數)
1C~1F 4 片段大小, 跟塊大小一模一樣
20~23 4 每個塊組中包含的塊數量
24~27 4 每個塊組中包含的片段數量, 跟包含的快數量一致
28~2B 4 每個塊組中包含的inode節點數量
2C~2F 4 文件系統最后掛載時間
30~33 4 文件系統最后寫入時間
34~35 2 當前掛載數
36~37 2 最大掛載數
38~39 2 文件系統簽名標識 53EF
3A~3B 2 文件系統狀態, 正常, 錯誤, 恢復了孤立的inode節點
3C~3D 2 錯誤處理方式, 繼續, 以只讀方式掛載
3E~3F 2 輔版本號
40~43 4 最后進行一致性檢查的時間
44~47 4 一致性檢查的間隔時間
48~4B 4 創建本文件系統的操作系統
4C~4F 4 主版本號, 只有該值為1的時候, 偏移54之后的擴展超級塊的一些動態屬性值才是有意義的
50~51 2 默認為UID的保留塊
52~53 2 默認為GID的保留塊
54~57 2 第一個非保留的inode節點號, 即用戶可以使用的第一個inode節點號
58~59 2 每個inode節點的大小字節數
5A~5B 2 本超級塊所在的塊組號
5C~5F 4 兼容標識特征
60~63 4 非兼容標識特征
64~67 4 只讀兼容特征標識
68~77 16 文件系統ID號
78~87 16 卷名
88~C7 64 最后的掛載路徑
C8~CB 4 位圖使用的運算法則
CC~CC 1 文件再分配的塊數
CD~CD 1 目錄再分配的塊數
CE~CF 2 未使用
D0~DF 16 日志ID
E0~E3 4 日志inode節點
E4~E7 4 日志設備
E8~EB 4 孤立的inode節點表
EC~3FF 788 未使用

塊組描述符詳細信息

每個塊組描述符占用32個字節, 其數據結構如下:

偏移(16進制) 字節數 含義&解釋
00~03 4 塊位圖起始地址(塊號)
04~07 4 inode節點位圖起始地址(塊號)
08~0B 4 inode節點表起始地址(塊號)
0C~0D 2 塊組中空閑塊數
0E~0F 2 塊組中空閑inode節點數
10~11 2 塊組中的目錄數
12~1F - 未使用

inode信息

每個inode會被分配給一個目錄或者一個文件, 每個inode包含了128個字節, 里面包含了這個文件的各種meta信息。

在所有inode中, 1~10號會用作保留給內核使用, 在這些保留節點中, 2號節點用於存儲根目錄信息, 1號表示壞塊, 8號表示日志文件信息。

第一個用戶可見的都是從11號inode開始, 11號節點一般用作lost+found目錄, 當檢查程序發現一個inode節點已經被分配, 但是沒有文件名指向他的時候, 就會把他添加到lost+found目錄中並賦予一個新的文件名。

inode通過三級指針的方式來找到文件數據最終存儲的數據塊, 見下圖:

inode查找文件塊過程

這種方式能保證小文件的讀取效率的同時, 也支持大文件的讀取。

目錄項

在ext文件系統中, 每個目錄也對應一個inode節點, 該inode節點對應的數據塊里面會存儲該目錄下所有文件/目錄的信息。

每個文件/目錄對應的信息就叫目錄項, 目錄項包含的內容也很簡單, 主要就是文件名和指向該文件名的inode指針, 詳細信息如下:

偏移(16進制) 字節數 含義&解釋
00~03 4 inode節點號
04~05 2 本目錄項的長度字節數
06~06 1 名字長度字節數
07~07 1 文件類型
08~ 不定長度 名字的ascii碼

當文件刪除的時候, 不會真正刪除文件, 會將該文件所屬目錄對應的目錄項給刪除, 同時將對應數據塊在快位圖表中標記為0。

鏈接

  1. 硬鏈接是指在另外一個目錄對應的目錄項中增加一個目錄項。硬鏈接建立之后, 用戶無法通過文件名來判斷到底哪個是原文件名, 哪個是鏈接名;
  2. 軟連接是一種文件類型, 該文件里面就存儲源文件的完整路徑, 如果源文件完整路徑長度小於60個字節, 那么就將該值直接存儲在inode節點表中, 避免浪費數據塊;

分配策略

  1. 首先判斷應該在哪個塊組中分配
    1. 如果是為文件創建節點
      1. 默認會在其父目錄所在的組中為其創建節點, 這樣可以確保一個目錄中所有文件都位於一個大致的區域中
      2. 如果父目錄所在組沒有空閑的節點或者空閑的塊了, 就到別的塊組中為該文件分配節點, 找尋別的塊組的算法如下
        1. 每次講當前組號加上2^N次方再求hash
        2. 如果上面的算法沒找到, 就線性查找
    2. 如果是為目錄創建節點
      1. 會將其分配到可用空間較多的塊組中, 分配算法如下:
        1. 首先利用超級塊中的剩余inode和剩余塊數字算出每個塊組的平均剩余數字, 然后依次找到一個大於平均值的塊組
        2. 如果沒找到, 就利用塊組描述符表中的信息, 找到一個最空閑的塊組
  2. 當一個數據塊分配給某文件之后
    1. 該塊原來的內容會被請出, inode節點對應的各種元信息會跟着做修改
    2. 如果是文件, 節點對應鏈接數會設置為1, 如果是目錄, 鏈接數會被設置為2

實際創建/刪除文件過程

我們創建一個/xuanku/file.txt, 該文件大小為10000字節, 文件塊大小為4096, 那么下面來看一下過程:

  1. 讀取文件系統的1024字節~2048字節, 即超級塊信息。通過超級塊得到快大小為4096, 每個塊組含有8192個塊以及2008個inode節點
  2. 讀取文件系統中第1個塊(即組描述符表), 得到所有塊組布局信息
  3. 訪問2號inode節點(即根節點), 通過讀取根節點數據塊信息, 假設讀到其位於5號塊
  4. 在第5號塊所有目錄項中從前往后遍歷, 直到找到文件名為xuanku的目錄項, 讀到該inode節點為4724
  5. 每個塊組有2008個inode, 用4724針對2008取模, 得到的結果是2號塊組
  6. 通過組描述符表中得到第2個塊組的inode節點表起始於16378號塊
  7. 從16378號塊讀取inode節點表中查找4724號對應的inode節點(708號表項), 查詢到該xuanku的目錄內容位於17216號塊
  8. 從17216塊讀取xuanku目錄項內容, 將file.txt相關信息更新到該塊的目錄項當中
  9. 然后開始為文件分配inode節點, 默認會放到父目錄所在塊組, 即2號塊組, 再次2號塊組的inode節點表16378, 開始從4724往后找到第一個可用的inode節點分配給該文件, 假設找到的是4850號inode。
  10. 然后就給4850號的inode位圖表設置為1, 組描述符的空閑inode節點數和超級塊的總空閑inode節點數都減1, 將inode節點的地址寫入file.txt對應的目錄項當中, 然后寫各種時間, 記錄日志
  11. file.txt需要3個塊的存儲空間, 通過2號塊組描述符找到塊位圖對應的塊, 並從前往后找到可用的塊。然后將對應的位設置為1, 並更新到inode節點當中
  12. 然后將文件的內容寫入到對應的塊中

下面再演示一下將該文件刪除的過程:

  1. 讀取文件系統的1024字節~2048字節, 即超級塊信息。通過超級塊得到快大小為4096, 每個塊組含有8192個塊以及2008個inode節點
  2. 讀取文件系統中第1個塊(即組描述符表), 得到所有塊組布局信息
  3. 訪問2號inode節點(即根節點), 通過讀取根節點數據塊信息, 假設讀到其位於5號塊
  4. 在第5號塊所有目錄項中從前往后遍歷, 直到找到文件名為xuanku的目錄項, 讀到該inode節點為4724
  5. 每個塊組有2008個inode, 用4724針對2008取模, 得到的結果是2號塊組
  6. 通過組描述符表中得到第2個塊組的inode節點表起始於16378號塊
  7. 從16378號塊讀取inode節點表中查找4724號對應的inode節點(708號表項), 查詢到該xuanku的目錄內容位於17216號塊
  8. 從17216塊讀取xuanku目錄項內容, 讀到file.txt的inode節點為4850
  9. 然后取消file.txt的目錄項分配, 修改系列xuanku目錄對應的目錄項信息
  10. 取消inode節點信息, 修改2號塊組對應的inode節點表信息, 將inode節點位設置為0, 更新塊組描述符和超級塊的空閑inode節點數加1
  11. 還要回收文件內容對應的6個塊空間, 將塊位圖表中的bit設置為0, 清除inode節點的塊指針, 更新塊組描述符和超級塊的空閑塊數加1

參考

  1. 數據重新 文件系統原理精解與數據恢復最佳實踐
  2. 磁盤分配方式. http://blog.csdn.net/liuqiyao_01/article/details/39156651
  3. ext在線調整大小. http://www.ibm.com/developerworks/cn/linux/l-cn-ext4resize/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM