複製鏈接
請複製以下鏈接發送給好友

Ext2

鎖定
EXT2第二代擴展文件系統英語:second extended filesystem,縮寫為 ext2),是LINUX內核所用的文件系統。它開始由Rémy Card設計,用以代替ext,於1993年1月加入linux核心支持之中。ext2 的經典實現為LINUX內核中的ext2fs文件系統驅動,最大可支持2TB的文件系統,至linux核心2.6版時,擴展到可支持32TB。其他的實現包括GNU Hurd,Mac OS X (第3方),Darwin (第3方),BSD。ext2為數個LINUX發行版的默認文件系統,如DebianRed Hat Linux [1] 

Ext2簡介

其單一文件大小與文件系統本身的容量上限與文件系統本身的簇大小有關,在一般常見的 x86 電腦系統中,簇最大為 4KB, 則單一文件大小上限為 2048GB, 而文件系統的容量上限為 16384GB。
但由於目前核心 2.4 所能使用的單一分割區最大隻有 2048GB,實際上能使用的文件系統容量最多也只有 2048GB。
至於Ext3文件系統,它屬於一種日誌文件系統,是對ext2系統的擴展。它兼容ext2,並且從ext2轉換成ext3並不複雜。

Ext2Ext2文件系統具有以下一般特點

1、當創建Ext2文件系統時,系統管理員可以根據預期的文件平均長度來選擇最佳的塊大小(從1024B——4096B)。例如,當文件的平均長度小於幾千字節時,塊的大小為1024B是最佳的,因為這會產生較少的內部碎片——也就是文件長度與存放塊的磁盤分區有較少的不匹配。另一方面,大的塊對於 大於幾千字節的文件通常比較合合適,因為這樣的磁盤傳送較少,因而減輕了系統的開銷 [1] 
2、當創建Ext2文件系統時,系統管理員可以根據在給定大小的分區上預計存放的文件數來選擇給該分區分配多少個索引節點。這可以有效地利用磁盤的空間。
3、文件系統把磁盤塊分為組。每組包含存放在相鄰磁道上的數據塊和索引節點。正是這種結構,使得可以用較少的磁盤平均尋道時間對存放在一個單獨塊組中的文件並行訪問。
4、在磁盤數據塊被實際使用之前,文件系統就把這些塊預分配給普通文件。因此當文件的大小增加時,因為物理上相鄰的幾個塊已被保留,這就減少了文件的碎片。
5、支持快速符號鏈接。如果符號鏈接表示一個短路徑名(小於或等於60個字符),就把它存放在索引節點中而不用通過由一個數據塊進行轉換。

Ext2Ext2還包含了一些使它既健壯又靈活的特點

1、文件更新策略的謹慎實現將系統崩潰的影響減到最少。我們只舉一個例子來體現這個優點:例如,當給文件創建一個硬鏈接時,首先增加磁盤索引節點中 的硬鏈接計數器,然後把這個新的名字加到合適的目錄中。在這種方式下,如果在更新索引節點後而改變這個目錄之前出現一個硬件故障,這樣即使索引節點的計數 器產生錯誤,但目錄是一致的。因此,儘管刪除文件時無法自動收回文件的數據塊,但並不導致災難性的後果。如果這種處理的順序相反(更新索引節點前改變目 錄),同樣的硬件故障將會導致危險的不一致,刪除原始的硬鏈接就會從磁盤刪除它的數據塊,但新的目錄項將指向一個不存在的索引節點。如果那個索引節點號以 後又被另外的文件所使用,那麼向這個舊目錄的寫操作將毀壞這個新的文件。
2、在啓動時支持對文件系統的狀態進行自動的一致性檢查。這種檢查是由外部程序e2fsck完成的,這個外部程序不僅可以在系統崩潰之後被激活,也 可以在一個預定義的文件系統安裝數(每次安裝操作之後對計數器加1)之後被激活,或者在自從最近檢查以來所花的預定義時間之後被激活。
3、支持不可變(immutable)的文件(不能修改、刪除和更名)和僅追加(append-only)的文件(只能把數據追加在文件尾)。
4、既與Unix System V Release 4(SVR4)相兼容,也與新文件的用户組ID的BSD語義相兼容。在SVR4中,新文件採用創建它的進程的用户組ID;而在BSD中,新文件繼承包含它 的目錄的用户組ID。Ext2包含一個安裝選項,由你指定採用哪種語義。
即使Ext2文件系統是如此成熟、穩定的程序,也還要考慮引入另外幾個負面特性。目前,一些負面特性已新的文件系統或外部補丁避免了。另外一些還僅僅處於計劃階段,但在一些情況下,已經在Ext2的索引節點中為這些特性引入新的字段。最重要的一些特點如下:
塊片(block fragmentation)
系統管理員對磁盤的訪問通常選擇較大的塊,因為計算機應用程序常常處理大文件。因此,在大塊上存放小文件就會浪費很多磁盤空間。這個問題可以通過把幾個文件存放在同一塊的不同片上來解決。
透明地處理壓縮和加密文件
這些新的選項(創建一個文件時必須指定)將允許用户透明地在磁盤上存放壓縮和(或)加密的文件版本。
邏輯刪除
一個undelete選項將允許用户在必要時很容易恢復以前已刪除的文件內容。
日誌
日誌避免文件系統在被突然卸載(例如,作為系統崩潰的後果)時對其自動進行的耗時檢查。
實際上,這些特點沒有一個正式地包含在Ext2文件系統中。有人可能説Ext2是這種成功的犧牲品;直到幾年前,它仍然是大多數Linux發佈公司採用的首選文件系統,每天有成千上萬的用户在使用它,這些用户會對用其他文件系統來代替Ext2的任何企圖產生質疑。
Ext2中缺少的最突出的功能就是日誌,日誌是高可用服務器必需的功能。為了平順過渡,日誌沒有引入到Ext2文件系統;但是,我們在後面 “Ext3文件系統”中會討論,完全與Ext2兼容的一種新文件系統已經創建,這種文件系統提供了日誌。不真正需要日誌的用户可以繼續使用良好而老式的Ext2文件系統,而其他用户可能採用這種新的文件系統。現在發行的大部分系統採用Ext3作為標準的文件系統。

Ext2Ext2文件系統格式

The Second Extended File System(ext2)文件系統是Linux系統中的標準文件系統,是通過對Minix的文件系統進行擴展而得到的,其存取文件的性能極好。
在ext2文件系統中,文件由inode(包含有文件的所有信息)進行唯一標識。一個文件可能對應多個文件名,只有在所有文件名都被刪除後,該文件才會被刪除。此外,同一文件在磁盤中存放和被打開時所對應的inode是不同的,並由內核負責同步。
ext2文件系統採用三級間接塊來存儲數據塊指針,並以塊(block,默認為1KB)為單位分配空間。其磁盤分配策略是儘可能將邏輯相鄰的文件分配到磁盤上物理相鄰的塊中,並儘可能將碎片分配給儘量少的文件,以從全局上提高性能。ext2文件系統將同一目錄下的文件(包括目錄)儘可能的放在同一個塊組中,但目錄則分佈在各個塊組中以實現負載均衡。在擴展文件時,會盡量一次性擴展8個連續塊給文件(以預留空間的形式實現)。

Ext2磁盤組織

在ext2系統中,所有元數據結構的大小均基於“塊”,而不是“扇區”。塊的大小隨文件系統的大小而有所不同。而一定數量的塊又組成一個塊組,每個塊組的起始部分有多種多樣的描述該塊組各種屬性的元數據結構。ext2系統中對各個結構的定義都包含在原始碼的include/linux/ext2_fs.h文件中。
1、超級塊
每個ext2文件系統都必須包含一個超級塊,其中存儲了該文件系統的大量基本信息,包括塊的大小、每塊組中包含的塊數等。同時,系統會對超級塊進行備份,備份被存放在塊組的第一個塊中。超級塊的起始位置為其所在分區的第1024個字節,佔用1KB的空間,其結構如下:
struct ext2_super_block {
__le32 s_inodes_count; // 文件系統中inode的總數
__le32 s_blocks_count; // 文件系統中塊的總數
__le32 s_r_blocks_count; // 保留塊的總數
__le32 s_free_blocks_count; // 未使用的塊的總數(包括保留塊)
__le32 s_free_inodes_count; // 未使用的inode的總數
__le32 s_first_data_block; // 塊ID,在小於1KB的文件系統中為0,大於1KB的文件系統中為1
__le32 s_log_block_size; // 用以計算塊的大小(1024算術左移該值即為塊大小)
__le32 s_log_frag_size; // 用以計算段大小(為正則1024算術左移該值,否則右移)
__le32 s_blocks_per_group; // 每個塊組中塊的總數
__le32 s_frags_per_group; // 每個塊組中段的總數
__le32 s_inodes_per_group; // 每個塊組中inode的總數
__le32 s_mtime; // POSIX中定義的文件系統裝載時間
__le32 s_wtime; // POSIX中定義的文件系統最近被寫入的時間
__le16 s_mnt_count; // 最近一次完整校驗後被裝載的次數
__le16 s_max_mnt_count; // 在進行完整校驗前還能被裝載的次數
__le16 s_magic; // 文件系統標誌,ext2中為0xEF53
__le16 s_state; // 文件系統的狀態
__le16 s_errors; // 文件系統發生錯誤時驅動程式應該執行的操作
__le16 s_minor_rev_level; // 局部修訂級別
__le32 s_lastcheck; // POSIX中定義的文件系統最近一次檢查的時間
__le32 s_checkinterval; // POSIX中定義的文件系統最近檢查的最大時間間隔
__le32 s_creator_os; // 生成該文件系統的操作系統
__le32 s_rev_level; // 修訂級別
__le16 s_def_resuid; // 報留塊的默認用户ID
__le16 s_def_resgid; // 保留塊的默認組ID
// 僅用於使用動態inode大小的修訂版(EXT2_DYNAMIC_REV)
__le32 s_first_ino; // 標準文件的第一個可用inode的索引(非動態為11)
__le16 s_inode_size; // inode結構的大小(非動態為128)
__le16 s_block_group_nr; // 保存此超級塊的塊組號
__le32 s_feature_compat; // 兼容特性掩碼
__le32 s_feature_incompat; // 不兼容特性掩碼
__le32 s_feature_ro_compat; // 只讀特性掩碼
__u8 s_uuid[16]; // 卷ID,應儘可能使每個文件系統的格式唯一
char s_volume_name[16]; // 卷名(只能為ISO-Latin-1字符集,以’\0’結束)
char s_last_mounted[64]; // 最近被安裝的目錄
__le32 s_algorithm_usage_bitmap; // 文件系統採用的壓縮算法
// 僅在EXT2_COMPAT_PREALLOC標誌被設置時有效
__u8 s_prealloc_blocks; // 預分配的塊數
__u8 s_prealloc_dir_blocks; // 給目錄預分配的塊數
__u16 s_padding1;
// 僅在EXT3_FEATURE_COMPAT_HAS_JOURNAL標誌被設置時有效,用以支持日誌
__u8 s_journal_uuid[16]; // 日誌超級塊的卷ID
__u32 s_journal_inum; // 日誌文件的inode數目
__u32 s_journal_dev; // 日誌文件的設備數
__u32 s_last_orphan; // 要刪除的inode列表的起始位置
__u32 s_hash_seed[4]; // HTREE散列種子
__u8 s_def_hash_version; // 默認使用的散列函數
__u8 s_reserved_char_pad;
__u16 s_reserved_word_pad;
__le32 s_default_mount_opts;
__le32 s_first_meta_bg; // 塊組的第一個元塊
__u32 s_reserved[190];
};
2、塊組描述符
一個塊組描述符用以描述一個塊組的屬性。塊組描述符組由若干塊組描述符組成,描述了文件系統中所有塊組的屬性,存放於超級塊所在塊的下一個塊中。一個塊組描述符的結構如下:
struct ext2_group_desc
{
__le32 bg_block_bitmap; // 塊位圖所在的第一個塊的塊ID
__le32 bg_inode_bitmap; // inode位圖所在的第一個塊的塊ID
__le32 bg_inode_table; // inode表所在的第一個塊的塊ID
__le16 bg_free_blocks_count; // 塊組中未使用的塊數
__le16 bg_free_inodes_count; // 塊組中未使用的inode數
__le16 bg_used_dirs_count; // 塊組分配的目錄的inode數
__le16 bg_pad;
__le32 bg_reserved[3];
};
3、塊位圖和inode位圖
塊位圖和inode位圖的每一位分別指出塊組中對應的那個塊或inode是否被使用。
4、inode表
inode表用於跟蹤定位每個文件,包括位置、大小等(但不包括文件名),一個塊組只有一個inode表。一個inode的結構如下:
struct ext2_inode {
__le16 i_mode; // 文件格式和訪問權限
__le16 i_uid; // 文件所有者ID的低16位
__le32 i_size; // 文件字節數
__le32 i_atime; // 文件上次被訪問的時間
__le32 i_ctime; // 文件創建時間
__le32 i_mtime; // 文件被修改的時間
__le32 i_dtime; // 文件被刪除的時間(如果存在則為0)
__le16 i_gid; // 文件所有組ID的低16位
__le16 i_links_count; // 此inode被連接的次數
__le32 i_blocks; // 文件已使用和保留的總塊數(以512B為單位)
__le32 i_flags; // 此inode訪問數據時ext2的實現方式
union {
struct {
__le32 l_i_reserved1; // 保留
} linux1;
struct {
__le32 h_i_translator; // “翻譯者”標籤
} hurd1;
struct {
__le32 m_i_reserved1; // 保留
} masix1;
} osd1; // 操作系統相關數據
__le32 i_block[EXT2_N_BLOCKS]; // 定位存儲文件的塊的數組,前12個為塊號,第13個為一級間接塊號,第14個為二級間接塊號,第15個為三級間接塊號
__le32 i_generation; // 用於NFS的文件版本
__le32 i_file_acl; // 包含擴展屬性的塊號,老版本中為0
__le32 i_dir_acl; // 表示文件的“High Size”,老版本中為0
__le32 i_faddr; // 文件最後一個段的地址
union {
struct {
__u8 l_i_frag; // 段號
__u8 l_i_fsize; // 段大小
__u16 i_pad1;
__le16 l_i_uid_high; // 文件所有者ID的高16位
__le16 l_i_gid_high; // 文件所有組ID的高16位
__u32 l_i_reserved2;
} linux2;
struct {
__u8 h_i_frag; // 段號
__u8 h_i_fsize; // 段大小
__le16 h_i_mode_high;
__le16 h_i_uid_high; // 文件所有者ID的高16位
__le16 h_i_gid_high; // 文件所有組ID的高16位
__le32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; // 段號
__u8 m_i_fsize; // 段大小
__u16 m_pad1;
__u32 m_i_reserved2[2];
} masix2;
} osd2; // 操作系統相關數據
};
數據塊中存放文件的內容,包括目錄表、擴展屬性、符號鏈接等。

Ext2目錄結構

在ext2文件系統中,目錄是作為文件存儲的。根目錄總是在inode表的第二項,而其子目錄則在根目錄文件的內容中定義。目錄項在include/linux/ext2_fs.h文件中定義,其結構如下:
struct ext2_dir_entry_2 {
__le32 inode; // 文件入口的inode號,0表示該項未使用
__le16 rec_len; // 目錄項長度
__u8 name_len; // 文件名包含的字符數
__u8 file_type; // 文件類型
char name[255]; // 文件名
};

Ext2文件擴展屬性

文件的屬性大多數是位於該文件的inode結構中的標準屬性,也還包含其他一些擴展屬性(於系統中所有的inode相關,通常用於增加額外的功能),在fs/ext2/xattr.h文件中定義。
inode的i_file_acl字段中保存擴展屬性的塊的塊號。屬性頭部項位於屬性塊的起始位置,其後為屬性入口項,而屬性值能根據屬性入口項找到所在位置。
1、屬性頭部項
struct ext2_xattr_header {
__le32 h_magic; // 標識碼,為0xEA020000
__le32 h_refcount; // 屬性塊被鏈接的數目
__le32 h_blocks; // 用於擴展屬性的塊數
__le32 h_hash; // 所有屬性的哈希值
__u32 h_reserved[4];
};
2、屬性入口項
struct ext2_xattr_entry {
__u8 e_name_len; // 屬性名長度
__u8 e_name_index; // 屬性名索引
__le16 e_value_offs; // 屬性值在值塊中的偏移量
__le32 e_value_block; // 保存值的塊的塊號
__le32 e_value_size; // 屬性值長度
__le32 e_hash; // 屬性名和值的哈希值
char e_name[0]; // 屬性名
};
參考資料
  • 1.    《數據恢復技術》