第十一章 EXT2文件系统
1.文件系统组成
0 | 1 | 2 | 3-7 | 8 | 9 | 10-32 | 33-x |
---|---|---|---|---|---|---|---|
引导块 | 超级块 | 块组描述符 | 保留块 | 块位图 | 索引节点位图 | 索引节点 | 数据块 |
2.引导块
容纳从磁盘引导操作系统的引导程序。
3.超级块
容纳整个文件系统的信息。
struct et2_super block {
u32 s_inodes_count; /* Inodes count */
u32 s_blocks_count; /* Blocks count */
u32 s_r_blocks_count; /* Reserved blocks count */
u32 s_free blocks_count; /* Free blocks count */
u32 s_free_inodes_count; /* Free inodes count */
u32 s_first_data_block; /* First Data Block */
u32 s_log block_size; /* Block size */
u32 s_log_cluster_size; /* Al1ocation cluster size */
u32 s_blocks per_group; /* # Blocks per group * /
u32 s_clusters per_group; /* # Fragments per group */
u32 s_inodes_per_group; /* # Inodes per group * /
u32 s_mtime; /* Mount time * /
u32 s_wtime; /* write time */
u16 s_mnt_count; /* Mount coune* /
s16 s_max_ntcount; /* Maximal mount count */
u16 B_magic; /* Magic signature */
//more non-essential fields
u16 s_inode_size; /* size of inode structure*/
}
3.索引节点
每个文件都用一个128字节(EXT4中的是256字节)的独特索引节点结构体表示。
struct ext2_inode {
u16 i_mode; // 16 bits =|ttttlugs|rwx|rwx|rwxl
u16 i_uid; // owmer uid
u32 i_size; // file size in bytes
u32 i_atime; //time fields in seconds
u32 i_ctime; // since 00:00:00,1-1-1970
u32 i_mtime;
u32 _dtime;
u16 i_gid; // group ID
u16 i_links_count;// hard-link count
u32 i_blocks; // number of 512-byte sectors
u32 i_flags; //IGNORE
u32 i_reservedl;// IGNORE
u32 i_block[15];// See details below
u32 _pad[7]; // for inode size = 128 bytes
}
4.结构图
5.邮差算法
LA <=> BA:
LA = info
BA = (blcok, inode)
INODES_PER_BLCOK = BLCOK_SIZE/sizeof(INODE)
blcok = (info - 1) * INODES_PER_BLCOK + inode_table;
inode = (info - 1) % INODES_PER_BLCOK
6.遍历文件树
(1)遍历算法
a.读取超级块;
b.读取块组描述符块(1 + s_first_data_block),以访问组0描述符。并从块组描述符的bg_inode_table条目中找到索引节点的起始块编号,将其成为InodesBeginBlock;
c.读取InodesBeginBlock,获取/的索引节点,即INODE#2;
d.将路径名标记为组件字符串,假设组件数量为恥例如,如果路径名=/a/b/c,则组 件字符串是“a”“b”“c”,其中n = 3。用name[0], namefl],…,name[n-l]来表示组件
e.从步骤c中的根索引节点开始,在其数据块中搜索name[0]。目录索引节点的每个数据块都包含 以下形式的dir entry结构体:
(ino rec_len name_len NAME] [ino rec_len name_len NAME)
其中NAME是一系列nlen字符,不含终止NULLO对于每个数据块,将该块读入内存 并使用dir_entry *dp指向加载的数据块。然后使用name」en将NAME提取为字符串,并与 namefO]进行比较。如果它们不匹配,贝U通过以下代码转到下一个dir_entry:
dp * (dir_entry *)((char *)dp + dp->rec_len))
继续搜索。如果存在name[0],则可以找到它的dir_entry,从而找到它的索引节点号。
f.使用索引节点号ino来定位相应的索引节点。回想前面的内容,ino从1开始计数。 使用邮差算法计算包含索引节点的磁盘块及其在该块中的偏移量。
blk = (ino - 1) * INODES_PER_BLOCK + InodesBeginBlock;
offset = (ino - 1) % INODES_PER_BLOCK;
然后在索引节点中读取/a,从中确定它是否是一个目录(DIR)。如果/a不是目录,则 不能有/a/b,因此搜索失败。如果它是目录,并且有更多需要搜索的组件,那么继续搜索 下一个组件name[l]o现在的问题是:在索引节点中搜索/a的name[l],与第(5 )步完全 相同。
g由于c到d步将会重复n次,所以最好编写一个搜索函数
u32 search(INODE *inodePtr, char *name)
(
// search for name in the data blocks of current DIR inode
// if found, return its ino; else return 0
)
调用search()n次,n为组件数量。
实践
在一个名为vdisk的虚拟磁盘文件上创建一个EXT2文件系统。