簡介
其單一檔案大小與檔案系統本身的容量上限與檔案系統本身的簇大小有關,在一般常見的 x86
電腦系統中,簇最大為 4KB, 則單一檔案大小上限為 2048GB, 而檔案系統的容量上限為 16384GB。
但由於目前核心 2.4 所能使用的單一分割區最大只有 2048GB,實際上能使用的檔案系統
容量最多也只有 2048GB。
至於
Ext3檔案系統,它屬於一種日誌檔案系統,是對ext2系統的擴展。它兼容ext2,並且從ext2轉換成
ext3並不複雜。
Ext2檔案系統具有以下一般特點:
1、當創建Ext2檔案系統時,系統管理員可以根據預期的檔案平均長度來選擇最佳的塊大小(從1024B——4096B)。例如,當檔案的平均長度小於幾千位元組時,塊的大小為1024B是最佳的,因為這會產生較少的內部碎片——也就是檔案長度與存放塊的磁碟分區有較少的不匹配。另一方面,大的塊對於 大於幾千位元組的檔案通常比較合合適,因為這樣的磁碟傳送較少,因而減輕了系統的開銷。
2、當創建Ext2檔案系統時,系統管理員可以根據在給定大小的分區上預計存放的檔案數來選擇給該分區分配多少個索引節點。這可以有效地利用磁碟的空間。
3、檔案系統把磁碟塊分為組。每組包含存放在相鄰磁軌上的數據塊和索引節點。正是這種結構,使得可以用較少的磁碟平均尋道時間對存放在一個單獨塊組中的檔案並行訪問。
4、在磁碟數據塊被實際使用之前,檔案系統就把這些塊預分配給普通檔案。因此當檔案的大小增加時,因為物理上相鄰的幾個塊已被保留,這就減少了檔案的碎片。
5、支持快速符號連結。如果符號連結表示一個短路徑名(小於或等於60個字元),就把它存放在索引節點中而不用通過由一個數據塊進行轉換。
Ext2還包含了一些使它既健壯又靈活的特點:
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作為標準的檔案系統。
Ext2檔案系統格式
The Second Extended File System(ext2)檔案系統是Linux系統中的標準檔案系統,是通過對Minix的檔案系統進行擴展而得到的,其存取檔案的性能極好。
在ext2檔案系統中,檔案由inode(包含有檔案的所有信息)進行唯一標識。一個檔案可能對應多個檔案名稱,只有在所有檔案名稱都被刪除後,該檔案才會被刪除。此外,同一檔案在
磁碟中存放和被打開時所對應的inode是不同的,並由
核心負責同步。
ext2檔案系統採用三級間接塊來存儲
數據塊指針,並以塊(block,默認為1KB)為單位分配空間。其磁碟分配策略是儘可能將邏輯相鄰的檔案分配到磁碟上物理相鄰的塊中,並儘可能將碎片分配給儘量少的檔案,以從全局上提高性能。ext2檔案系統將同一目錄下的檔案(包括目錄)儘可能的放在同一個塊組中,但目錄則分布在各個塊組中以實現
負載均衡。在擴展檔案時,會儘量一次性擴展8個連續塊給檔案(以預留空間的形式實現)。
磁碟組織
在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];
};
塊點陣圖和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;
__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檔案系統中,目錄是作為檔案存儲的。根目錄總是在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]; // 檔案名稱
};
檔案擴展屬性
檔案的屬性大多數是位於該檔案的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]; // 屬性名
};