Linux內核文檔翻譯之Squashfs文件系統

       對於使用openwrt的嵌入式系統來說,因爲硬件絕大多數採用Flash,因此一般使用squashfs文件系統和jffs2文件系統。前者是隻讀的,後者是可寫的。我們一般會把jffs2 mount到某個目錄下。這樣就存在某些目錄如/bin是隻讀的(squashfs),某些目錄是可讀寫的(jffs2),這樣對文件的操作會依賴於文件系統的屬性和文件的路徑。

       openwrt使用了mini_fo文件系統,從用戶的使用角度看,會覺得整個文件系統都是可寫的。用戶可以任意修改、刪除、添加文件。這種文件系統可以認爲是在squashfs和jffs2的文件系統之上實現了一個符號鏈接,如果用戶讀取只讀文件,則鏈接到squashfs文件系統讀取,如果用戶對只讀文件進行了修改,則將修改的文件放到jffs2文件系統上,並修改鏈接。
    如果用戶的系統不採用jffs2系統,openwrt會使用ramfs,依舊可以實現上面的功能,不過系統重啓後,修改會丟失。

/************************************************************************************************************************************/

 原創作品,轉載時請務必以超鏈接形式標明文章原始出處:http://blog.csdn.net/gqb666/article/details/12946629,作者:gqb666  
/************************************************************************************************************************************/

       來說下Linux下的squashfs文件系統,使用squashfs文件系統作爲只讀分區,使用mini_fo文件將squashfs和jffs2文件系統組合成可寫可讀根文件系統,當寫操作時會將寫入內容放到jffs2文件系統中,爲了深入研究squashfs文件系統工作原理,先將內核文檔翻譯一下。

原文件位置:Linux源碼目錄\Documentation\filesystems\squashfs.txt

SQUASHFS 4.0 FILESYSTEM 

=======================

Squashfs是Linux下的一種只讀壓縮文件系統類型。它使用zlib/lzo/xz等壓縮算法來壓縮文件,節點及目錄。Squashfs文件系統內的節點非常小巧並且所有的數據塊都排列緊湊,通過這種方式來降低數據存儲開銷。數據塊大小可以取在4KB到1MB,但默認大小爲128KB。

Squashfs爲通用只讀文件系統所用,常用來保存歸檔文件(如 .tar.gz文件等),還有用於存儲空間受限的系統,更有甚者,嵌入式設備中用於恢復出廠設置的只讀分區來用。

郵件列表: [email protected]
官方網站: www.squashfs.org

1. 文件系統特性
-------------------------------------------

Squashfs 文件系統 VS Cramfs 文件系統特性:


Squashfs 會將數據、節點及目錄進行壓縮。另外,節點和目錄數據是字節對齊並且是高度緊湊的。每個壓縮的節點平均僅佔用8字節長度(確切長度會因爲文件類型而不同,比如普通文件、目錄、符號鏈接及塊/字符設備節點等)。

2. 使用 Squashfs文件系統
-----------------
squashfs作爲一種只讀文件,必須用mksquashfs工具來創建壓縮的squashfs文件系統。mksquash工具及unsquashfs等工具可以從http://www.squashfs.org網站獲取。這些squashfs相關工具代碼樹現在已經被集成到kernel.org內:
git://git.kernel.org/pub/scm/fs/squashfs/squashfs-tools.git

3. Squashfs 文件系統設計
-----------------------------
Squashfs 文件系統最多包含9種字節對齊的模塊:

壓縮的數據塊就像從某個目錄裏讀文件一樣寫到文件系統並進行冗餘檢查。當文件數據被寫入到文件系統, completed inode, directory, fragment, export, uid/gid lookup 和xattr tables也會同時被寫入到文件系統裏面。 

3.1 索引節點
----------
元數據 (索引節點和目錄) 一般被壓縮成爲8KB大小的數據塊。每個壓縮塊前都有2字節的前綴頭,當某數據塊被壓縮時前綴頭的最高位會被置1,當然-noI 選項被置1或者壓縮部分的大小大於未壓縮大小時,數據塊將會被解壓。

索引節點會被打包進元數據塊,但並未以塊大小對齊,因此索引節點會覆蓋壓縮數據塊。索引節點是用一個48位數來標示的,這個48位數包括含有該索引點的壓縮元數據塊的位置及索引節點在塊內的偏移量<block,offset>。
爲了提高壓縮率,Squashfs文件系統針對不同的文件類型(普通文件、目錄文件、設備文件等等)採用不同的索引節點,並且這些不同索引節點有不同的數據位數。爲了進一步提高壓縮率,普通文件索引節點和目錄文件索引節點定義如下:爲常用的普通文件和目錄文件優化並且保存了額外信息的節點類型

3.2 目錄
---------------
和索引節點一樣,目錄文件同樣是被打包進元數據塊內,只是被存放在目錄表內而以。同樣的,目錄文件的存取是通過包含該目錄的元數據塊的起始地址及塊內偏移來完成的<block,offset>。

目錄不是通過簡單的文件名列表而是一種稍顯巧妙的方式來組織的。該組織方式充分利用了文件的索引節點會存放在同一元數據塊內的事實,因此可能共享其塊起始地址。因此目錄組織結構包括兩部分:包含共享塊起始地址的目錄頭和使用了共享塊起始地址的順序目錄項。當索引節點的起始塊地址改變時,目錄頭也會被修改。目錄頭和目錄項會儘可能的重複。
目錄包含一個用來快速檢索文件的目錄索引,並且目錄是有序的。目錄索引會在每個元數據塊儲存一個條目,而每個條目裏則存放着該元數據塊的第一個目錄頭對應的索引或者文件名。目錄名是以字母順序排列的,檢索時內核會線性地搜索大於被查找文件名第一個字母的文件名,這樣包含該文件名的元數據塊的位置就可以確定了。這種方法的核心所在是這種索引方法可以保證要檢索的元數據塊不依賴於目錄的長度,另外的優點是這種方法不需要額外的內存及磁盤存儲空間。

3.3 文件數據
-------------
普通文件由一系列連續的壓縮數據塊及壓縮片段塊組成(尾端壓縮塊)。每個數據塊的壓縮大小存放在文件節點的塊列表內。
爲了加快讀大“數據”(256MB或者更大)的速度,squashfs實現了一個緩存從塊索引映射到磁盤上的數據的緩存索引。
這種緩存索引允許squashfs處理大文件(1.75TiB級別的)但僅僅在磁盤上保存一個簡單小巧的塊列表。這種緩存又被劃分爲更小的槽,每個槽可以緩存224GiB大小的文件(128KiB塊);大文件即可以使用多個槽,比如1.75TiB使用8個槽。緩存索引被設計爲一種內存高效的方法,默認情況下大小爲16KiB。

3.4 片段檢索表
-------------------------

常規文件可以包含一些被映射了磁盤位置的片段索引和使用片段檢索表的壓縮數據大小。這種片段檢索表本身被壓縮地存儲元在數據塊內部。第二個索引表用來定位這些,第二個索引表可以提高存取速度(因爲它很小),在掛載時讀取並緩存在內存中。


3.5 uid/gid索引表
------------------------
出於空間效率考慮,普通文件保存了uid/gid索引,這些索引將最終被轉換爲使用檢索表32位uid/gid。這些索引表會被壓縮進元數據塊內。第二個索引表用來定位這些,第二個索引表可以提高存取速度(因爲它很小),在掛載時讀取並緩存在內存中。

3.6 導出表
----------------

爲了使Squashfs文件系統成爲可導出文件系統(通過NFS等),可以選擇(通過mksquashfs工具加-no-exports來禁用)包含一個inode號到inode磁盤磁盤位置的查找表。需要使用Squashfs來使能inode號到inode在磁盤上的位置的映射,當導出代碼重新實例過期/刷新的inode 時這個很有必要。這個導出表會壓縮進元數據塊。第二個索引表用來定位這些,第二個索引表可以提高存取速度(因爲它很小),在掛載時讀取並緩存在內存中。


3.7 擴展屬性表
---------------

擴展屬性表包含每個節點的擴展屬性。 每個索引節點的擴展屬性被存儲在一個列表中,每個列表條目包含一個type,name和value字段。type字段使用擴展屬性前綴("user","trusted."等)來編碼,它也確定name/value字段應該被解釋。目前type用來指明value值是否內嵌存儲(在這種情況下,value字段包含擴展屬性值) ,或者外部存儲(在這種情況下,value字段中存儲有擴展屬性實際存儲位置的指針) 。這使得較大的屬性值可以通過外部存儲的方式來提高掃描檢索性能,同時 它還允許該值被"反拷貝",該值僅被存儲一次,其他的就可以併發使用一個引用來訪問該值。

擴展屬性列表被打包壓縮成8K元數據塊。爲了減少節點的開銷,一個32位擴展屬性ID被保存而不是存儲擴展屬性的磁盤位置到每個inode內。這個32位擴展屬性ID使用第二個擴展ID檢索表映射了擴展屬性列表的位置。

4. 未來的工作及突出問題
-------------------------------
4.1 未來工作列表
-------------
實現 ACL 支持

4.2 Squashfs 內部緩存
---------------------------

Squashfs的塊是以壓縮形式存在的。爲了避免重複解壓最近訪問過的數據Squashfs的使用兩個小的元數據和片段高速緩存。
這種緩存並不用於那些壓縮並在頁高速緩存裏通過正常方式緩存的數據塊,而是用於臨時緩存作爲一個元數據的結果讀取的片段和元數據塊(即inode或目錄)或片段連接。因爲元數據和片段會被一起打包成塊(以獲得更大的壓縮),讀取特定的元數據或片段/片段會導致其他元數據檢索被擠滿,這可能是因爲本地引用在不久後會被讀取。臨時緩存確保它們可在不久的將來不需要額外的讀解壓縮的情況下被訪問。

將來內部緩存將會被內核頁面緩存替換,但由於內核頁面緩存頁是基於頁大小單位來操作的,因此可能會引入額外鎖及相關競態條件的複雜性。

發佈了41 篇原創文章 · 獲贊 38 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章