預備知識
一、預備知識
1、block
對於ext2(ext3類似)檔案系統來說,硬碟分區首先被劃分為一個個的block,同一個ext2檔案系統上的每個block大小都是一樣的。但是對於不同的ext2檔案系統,block的大小可以有區別。典型的block大小是1024 bytes或者4096 bytes。這個大小在創建ext2檔案系統的時候被決定,它可以由系統管理員指定,也可以由檔案系統的創建程式根據硬碟分區的大小,自動選擇一個較合理的值。
一個硬碟分區上的block計數是從0開始的,並且這個計數對於這個硬碟分區來說是全局性質的。
2、block group和group descriptor
硬碟分區中所有block被聚在一起分成幾個大的block group,其中每個block group中有多少個block是固定的。
每個block group都相對應一個group descriptor,這些group descriptor被聚在一起放在硬碟分區的開頭部分,跟在super block的後面。在每個group descriptor當中有幾個重要的block指針,指向block group的inode table、block bitmap和inode bitmap。
3、inode table、block bitmap和inode bitmap
以上三個結構記載了其所屬block group的許多信息,他們依次被存放在這個block group的開頭部分,由該block group所對應的group descriptor中的指針所指向。
定義介紹
二、super block的定義
super block的中文名稱是超級塊,它是硬碟分區開頭——開頭的第一個byte是byte 0,從 byte 1024開始往後的一部分數據。由於 block size最小是 1024 bytes,所以super block可能是在block 1中(此時block 的大小正好是 1024 bytes),也可能是在block 0中。
超級塊中的數據其實就是檔案卷的控制信息部分,也可以說它是卷資源表,有關檔案卷的大部分信息都保存在這裡。例如:硬碟分區中每個block的大小、硬碟分區上一共有多少個block group、以及每個block group中有多少個inode。(下有詳細說明)
結構涵義
三、super block的結構和涵義
struct ext3_super_block {
/*00*/ __u32 s_inodes_count; /* inodes 計數 */
__u32 s_blocks_count; /* blocks 計數 */
__u32 s_r_blocks_count; /* 保留的 blocks 計數 */
__u32 s_free_blocks_count; /* 空閒的 blocks 計數 */
/*10*/ __u32 s_free_inodes_count; /* 空閒的 inodes 計數 */
__u32 s_first_data_block;/* 第一個數據 block */
__u32 s_log_block_size; /* block 的大小 */
__s32 s_log_frag_size; /* 可以忽略 */
/*20*/ __u32 s_blocks_per_group;/* 每 block group 的 block 數量 */
__u32 s_frags_per_group; /* 可以忽略 */
__u32 s_inodes_per_group;/* 每 block group 的 inode 數量 */
__u32 s_mtime;/* Mount time */
/*30*/ __u32 s_wtime;/* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic;/* Magic 簽名 */
__u16 s_state;/* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
/*40*/ __u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* 可以忽略 */
__u32 s_rev_level; /* Revision level */
/*50*/ __u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
/*60*/ __u32 s_feature_incompat;/* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
/*68*/ __u8s_uuid[16]; /* 128-bit uuid for volume */
/*78*/ chars_volume_name[16]; /* volume name */
/*88*/ chars_last_mounted[64];/* directory where last mounted */
/*C8*/ __u32 s_algorithm_usage_bitmap; /* 可以忽略 */
__u8s_prealloc_blocks; /* 可以忽略 */
__u8s_prealloc_dir_blocks; /* 可以忽略 */
__u16 s_padding1;/* 可以忽略 */
/*D0*/ __u8s_journal_uuid[16]; /* uuid of journal superblock */
/*E0*/ __u32 s_journal_inum; /* 日誌檔案的 inode 號數 */
__u32 s_journal_dev; /* 日誌檔案的設備號 */
__u32 s_last_orphan; /* start of list of inodes to delete */
/*EC*/ __u32 s_reserved[197]; /* 可以忽略 */
};
重要成員
四、super block的幾個重要成員
1、Magic 簽名
對於ext2和ext3檔案系統來說,這個欄位的值應該正好等於0xEF53。如果不等的話,那么這個硬碟分區上肯定不是一個正常的ext2或ext3檔案系統。
2、s_log_block_size
從這個欄位,我們可以得出真正的block的大小。我們把真正block的大小記作B,B=1 << s_log_block_size + 10),單位是bytes。舉例來說,如果這個欄位是0,那么block的大小就是 1024bytes,這正好就是最小的block大小;如果這個欄位是2,那么block大小就是4096 bytes。從這裡我們就得到了block的大小這一非常重要的數據。
3、s_blocks_count和s_blocks_per_group
通過這兩個成員,我們可以得到硬碟分區上一共有多少個block group,或者說一共有多少個group descriptors
s_blocks_count記錄了硬碟分區上的block的總數,而s_blocks_per_group記錄了每個group中有多少個block。顯然,檔案系統上的block groups數量,我們把它記作G,G=(s_blocks_count-s_first_data_block-1)/s_blocks_per_group+1。為什麼要減去s_first_data_block,因為s_blocks_count是硬碟分區上全部的block的數量,而在s_first_data_block之前的block是不歸block group管的,所以當然要減去。最後為什麼又要加一,這是因為尾巴上可能多出來一些block,這些block我們要把它劃在一個相對較小的group裡面。
4、s_inodes_per_group
s_inodes_per_group記載了每個block group中有多少個inode。在從已知的inode號,讀取這個inode數據的過程中,s_inodes_per_group起到了至關重要的作用。
用我們得到的inode號數除以s_inodes_per_group,我們就知道了我們要的這個inode是在哪一個block group裡面,這個除法的餘數也告訴我們,我們要的這個inode是這個block group裡面的第幾個inode;然後,我們可以先找到這個block group的group descriptor,從這個descriptor,我們找到這個group的inode table,再從inode table找到我們要的第幾個 inode,再以後,我們就可以開始讀取inode中的用戶數據了。這個公式是這樣的:
block_group = (ino - 1) / s_inodes_per_group。這裡ino就是我們的inode號數
offset = (ino - 1) % s_inodes_per_group,這個offset就指出了我們要的inode是這個block group裡面的第幾個inode。