Squashfs 4.0 檔案系統¶
Squashfs 是一個用於 Linux 的壓縮只讀檔案系統。
它使用 zlib、lz4、lzo、xz 或 zstd 壓縮來壓縮檔案、inode 和目錄。系統中的 inode 非常小,並且所有塊都被打包以最大限度地減少資料開銷。支援大於 4K 的塊大小,最大可達 1M 位元組(預設塊大小為 128K)。
Squashfs 適用於通用的只讀檔案系統用途,適用於歸檔用途(即在可以使用 .tar.gz 檔案的情況下),以及在受限的塊裝置/記憶體系統(例如,嵌入式系統)中,需要低開銷。
郵件列表(核心程式碼):linux-fsdevel@vger.kernel.org 網站:github.com/plougher/squashfs-tools
1. 檔案系統特性¶
Squashfs 檔案系統特性與 Cramfs 比較
最大檔案系統大小 |
2^64 |
256 MiB |
最大檔案大小 |
~ 2 TiB |
16 MiB |
最大檔案數 |
無限制 |
無限制 |
最大目錄數 |
無限制 |
無限制 |
每個目錄的最大條目數 |
無限制 |
無限制 |
最大塊大小 |
1 MiB |
4 KiB |
元資料壓縮 |
是 |
否 |
目錄索引 |
是 |
否 |
稀疏檔案支援 |
是 |
否 |
尾端打包(片段) |
是 |
否 |
可匯出(NFS 等) |
是 |
否 |
硬連結支援 |
是 |
否 |
readdir 中的“.”和“..” |
是 |
否 |
真實的 inode 編號 |
是 |
否 |
32 位 uids/gids |
是 |
否 |
檔案建立時間 |
是 |
否 |
Xattr 支援 |
是 |
否 |
ACL 支援 |
否 |
否 |
Squashfs 壓縮資料、inode 和目錄。此外,inode 和目錄資料高度壓縮,並在位元組邊界上打包。每個壓縮 inode 的平均長度為 8 位元組(確切長度隨檔案型別而變化,即常規檔案、目錄、符號連結和塊/字元裝置 inode 具有不同的大小)。
2. 使用 Squashfs¶
由於 squashfs 是隻讀檔案系統,因此必須使用 mksquashfs 程式來建立填充的 squashfs 檔案系統。這個和其他 squashfs 實用程式很可能由您的 linux 發行版打包(稱為 squashfs-tools)。原始碼可以從 github.com/plougher/squashfs-tools 獲取。使用說明也可以從該站點獲取。
2.1 掛載選項¶
errors=%s |
指定 squashfs 錯誤是否觸發核心 panic
|
||||||||||
threads=%s |
選擇解壓縮模式或執行緒數 如果設定了 SQUASHFS_CHOICE_DECOMP_BY_MOUNT
如果 SQUASHFS_CHOICE_DECOMP_BY_MOUNT 未設定,並且 SQUASHFS_DECOMP_MULTI 和 SQUASHFS_MOUNT_DECOMP_THREADS 都已設定
|
3. Squashfs 檔案系統設計¶
一個 squashfs 檔案系統最多由九個部分組成,這些部分按位元組對齊打包在一起
---------------
| superblock |
|---------------|
| compression |
| options |
|---------------|
| datablocks |
| & fragments |
|---------------|
| inode table |
|---------------|
| directory |
| table |
|---------------|
| fragment |
| table |
|---------------|
| export |
| table |
|---------------|
| uid/gid |
| lookup table |
|---------------|
| xattr |
| table |
---------------
壓縮資料塊在從源目錄讀取檔案時寫入檔案系統,並檢查重複項。一旦寫入所有檔案資料,就會寫入已完成的 inode、目錄、片段、匯出、uid/gid 查詢和 xattr 表。
3.1 壓縮選項¶
壓縮器可以選擇支援壓縮特定選項(例如字典大小)。如果使用了非預設壓縮選項,則將這些選項儲存在此處。
3.2 Inode¶
元資料(inode 和目錄)在 8K 位元組的塊中壓縮。每個壓縮塊都以兩個位元組的長度為字首,如果該塊未壓縮,則設定最高位。如果設定了 -noI 選項,或者如果壓縮塊大於未壓縮塊,則該塊將未壓縮。
Inode 被打包到元資料塊中,並且不對齊到塊邊界,因此 inode 重疊壓縮塊。Inode 由一個 48 位數字標識,該數字對包含 inode 的壓縮元資料塊的位置以及 inode 放置在該塊中的位元組偏移量進行編碼 (<塊, 偏移量>)。
為了最大化壓縮,每種檔案型別(常規檔案、目錄、裝置等)都有不同的 inode,inode 內容和長度隨型別而變化。
為了進一步最大化壓縮,定義了兩種型別的常規檔案 inode 和目錄 inode:為頻繁出現的常規檔案和目錄最佳化的 inode,以及必須儲存額外資訊的擴充套件型別。
3.3 目錄¶
與 inode 一樣,目錄被打包到壓縮的元資料塊中,儲存在目錄表中。使用包含目錄的元塊的起始地址和解壓縮塊的偏移量 (<塊, 偏移量>) 訪問目錄。
目錄以稍微複雜的方式組織,而不僅僅是檔名列表。該組織利用了這樣一個事實:檔案的 inode(在大多數情況下)將位於同一個壓縮元資料塊中,因此可以共享起始塊。因此,目錄以兩級列表組織,目錄標頭包含共享起始塊值,以及一系列目錄條目,每個條目共享共享起始塊。一旦/如果 inode 起始塊發生變化,就會寫入新的目錄標頭。目錄標頭/目錄條目列表會重複多次,直到需要為止。
目錄已排序,並且可以包含目錄索引以加快檔案查詢速度。目錄索引儲存每個元塊一個條目,每個條目儲存索引/檔名對映到每個元資料塊中的第一個目錄標頭。目錄按字母順序排序,在查詢時,索引會線性掃描,查詢按字母順序大於正在查詢的檔名的第一個檔名。此時,已經找到了檔名所在的元資料塊的位置。索引的總體思路是確保只需要解壓縮一個元資料塊即可進行查詢,而不管目錄的長度如何。該方案的優點是不需要額外的記憶體開銷,並且不需要磁碟上的額外儲存空間。
3.4 檔案資料¶
常規檔案由一系列連續的壓縮塊和/或壓縮片段塊(尾端打包塊)組成。每個資料塊的壓縮大小儲存在檔案 inode 中包含的塊列表中。
為了加快讀取“大”檔案(256 Mbytes 或更大)時對資料塊的訪問速度,程式碼實現了一個索引快取,該快取快取從塊索引到磁碟上的資料塊位置的對映。
索引快取允許 Squashfs 處理大檔案(高達 1.75 TiB),同時在磁碟上保留一個簡單且節省空間的塊列表。快取被分成多個槽,最多快取八個 224 GiB 檔案(128 KiB 塊)。更大的檔案使用多個槽,1.75 TiB 檔案使用所有 8 個槽。索引快取旨在節省記憶體,預設使用 16 KiB。
3.5 片段查詢表¶
常規檔案可以包含一個片段索引,該索引使用片段查詢表對映到磁碟上的片段位置和壓縮大小。此片段查詢表本身以壓縮形式儲存到元資料塊中。第二個索引表用於定位這些。為了加快訪問速度(並且因為它很小),此第二個索引表在掛載時讀取並快取在記憶體中。
3.6 Uid/gid 查詢表¶
為了提高空間效率,常規檔案儲存 uid 和 gid 索引,這些索引使用 id 查詢錶轉換為 32 位 uids/gids。此表以壓縮形式儲存到元資料塊中。第二個索引表用於定位這些。為了加快訪問速度(並且因為它很小),此第二個索引表在掛載時讀取並快取在記憶體中。
3.7 匯出表¶
為了使 Squashfs 檔案系統可匯出(透過 NFS 等),檔案系統可以選擇性地(使用 -no-exports Mksquashfs 選項停用)包含一個 inode 編號到 inode 磁碟位置查詢表。這是必需的,以便 Squashfs 將檔案控制代碼中傳遞的 inode 編號對映到磁碟上的 inode 位置,這在匯出程式碼重新例項化過期的/重新整理的 inode 時是必需的。
此表以壓縮形式儲存到元資料塊中。第二個索引表用於定位這些。為了加快訪問速度(並且因為它很小),此第二個索引表在掛載時讀取並快取在記憶體中。
3.8 Xattr 表¶
xattr 表包含每個 inode 的擴充套件屬性。每個 inode 的 xattr 儲存在一個列表中,每個列表條目包含一個型別、名稱和值欄位。型別欄位對 xattr 字首(“user.”、“trusted.” 等)進行編碼,並且還對應該如何解釋名稱/值欄位進行編碼。當前,該型別指示值是內聯儲存(在這種情況下,值欄位包含 xattr 值)還是離線儲存(在這種情況下,值欄位儲存對實際值的儲存位置的引用)。這允許離線儲存大值,從而提高掃描和查詢效能,並且還允許對值進行去重,該值儲存一次,所有其他出現都儲存對該值的離線引用。
xattr 列表被打包到壓縮的 8K 元資料塊中。為了減少 inode 中的開銷,而不是將 xattr 列表的磁碟上位置儲存在每個 inode 中,而是儲存一個 32 位 xattr id。此 xattr id 使用第二個 xattr id 查詢表對映到 xattr 列表的位置。
4. TODO 和未解決的問題¶
4.1 TODO 列表¶
實現 ACL 支援。
4.2 Squashfs 內部快取¶
Squashfs 中的塊是壓縮的。為了避免重複解壓縮最近訪問的資料,Squashfs 使用兩個小的元資料和片段快取。
該快取不用於檔案資料塊,這些資料塊以正常方式在頁面快取中解壓縮和快取。該快取用於臨時快取由於元資料(即 inode 或目錄)或片段訪問而讀取的片段和元資料塊。由於元資料和片段被打包到塊中(以獲得更大的壓縮),因此讀取特定的元資料或片段將檢索已與其打包的其他元資料/片段,由於引用區域性性,這些元資料/片段可能在不久的將來被讀取。臨時快取它們可確保它們可用於不久的將來的訪問,而無需額外的讀取和解壓縮。
將來,此內部快取可能會被使用核心頁面快取的實現所取代。由於頁面快取以頁面大小的單元執行,這可能會在鎖定和相關的競爭條件方面引入額外的複雜性。