学习笔记五 第十一章

EXT2文件系统

在Linux下,命令

mke2fs [-b blksize -N ninodes] device nblocks

在设备上创建一个带有nblocks个块(每个块大小为blksize字节)和ninodes个索引节点的EXT2文件系统。

例子命令:

dd if=/dev/zero of=vdisk bs=1024 count=1440
mke2fs vdisk 1440

在vdsik的虚拟擦盘文件上创建一个EXT2文件系统。

EXT2系统的布局如图11.1所示:

学习笔记五  第十一章

 

 Block#0: 引导块 B0是引导块,文件不会使用,起着一个引导作用。

 11.2.3超级块

Block#1:超级块(硬盘分区中字节偏移量为1024)B1是超级块,容纳整个文件系统的信息。

学习笔记五  第十一章

s_first_data_block: 0表示4KB块大小,1表示1KB块大小。它用于确定块组描述符的 起始块,即 s_first_data_block + 10
s_log_block_size :确定文件块大小,为 lKB*(2**s_log_block_size),例如:0 表示 1KB块大小,1表示2KB块大小,2表示4KB块大小等。最常用的块大小是用于小文件系 统的1KB和用于大文件系统的4KB。
s_mnt_count :已挂载文件系统的次数。当挂载计数达到max mnt count时,fsck会话 将*检查文件系统的一致性。
s_magic:文件系统类型的幻数。EXT2/3/4文件系统的幻数是0xEF53

块组描述符
Block#2:块组描述符块(硬盘上的s_first_data_block+l ) EXT2将磁盘块分成几个组。 每个组有8192个块(硬盘上的大小为32K)。每组用一个块组描述符结构体来描述。

学习笔记五  第十一章

块和索引节点位图
Block#8 :块位图(Bmap)(bg_block_bitmap)位图是用来表示某种项的位序列,例如 磁盘块或索引节点。位图用于分配和回收项。在位图中,0位表示对应项处于FREE状态, 1位表示对应项处于IN_USE状态。一个软盘有1440个块,但是Block#。未被文件系统使 用。所以,位图只有1439个有效位。无效位被视作IN_USE,设置为1。
Block#9 :索引节点位图(Imap) (bg_inode_bitmap) 一个索引节点就是用来代表一个 文件的数据结构° EXT2文件系统是使用有限数量的索引节点创建的。各索引节点的状态用 B9的Imap中的一个位表示。在EXT2 FS中,前10个索引节点是预留的。所以,空EXT2 FS的Imap以10个1开头,然后是0。无效位再次设置为1。

索引节点
Block#10:索引(开始)节点(bg_inode_table)每个文件都用一个128字节(EXT4中 是256字节)的唯一索引节点结构体表示。

学习笔记五  第十一章

直接块:i_block[0] Mi_block[ll],指向直接磁盘块」
间接块:i_block[12]指向一个包含256个块编号(对于1KB BLKSIZE)的磁盘块,每 个块编号指向一个磁盘块。
双重间接块:i_block[13]指向一个指向256个块的块,每个块指向256个磁盘块。
三重间接块:i_block[14]是三重间接块。对于“小型” EXT2文件系统,可以忽略它。
索引节点大小(128或256 )用于平均分割块大小(1KB或4KB),所以,每个索引 节点块都包含整数个索引节点 在简単的EXT2文件系统中,索引节点的数量是184个 (Linux默认值)。索引节点块数等于184/8-23个。因此,索引节点块为BI0至B32。每个索 引节点都有-个唯一的索引节点编号,即索引节点在索引节点块上的位置+1。注意,索引 节点位置从0开始计数,而索引节点编号从1开始计数。0索引节点编号表示没有索引节点一 根目录的索引节点编号为2。同样,磁盘块编号也从1开始计数,因为文件系统从未使用块 0。块编号0表示没有磁盘块。 在索引节点块后面的就是文件存储数据块。

11.2.8目录条目

目录包含dir_entry结构:

struct ext2_dir_entry_2{
    u32 inode;
    u16 rec_len;
    u8 name_len;
    u8 file_type;
    char name[EXT2_NAME_LEN];
};

遍历算法:

(1)读取超级块。检查幻数s_magic ( OxEF53),验证它确实是EXT2FS。

(2)读取块组描述符块(1+s_first_data_block),以访问组0描述符。从块组描述符的bg_inode_table条目中找到索引节点的起始块编号,并将其称为InodesBeginBlock 。

(3)读取 InodeBeginBlock,获取/的索引节点,即INODE #2。

(4)将路径名标记为组件字符串,假设组件数量为n。
例如,如果路径名=/a/b/c,则组件字符串是“a”"b”“c”,其中n =3。用name[0],name[1],…,name[n-1]来表示组件。

(5)

从(3)中的根索引节点开始,在其数据块中搜索name[0]。
为简单起见,我们可以假设某个目录中的条目数量很少,因此一个目录索引节点只有12个直接数据块。
有了这个假设,就可以在12个(非零)直接块中搜索name[0]。目录索引节点的每个数据块都包含以下形式的dir_entry结构体:
[ino rec_len name_len NANE] [ino rec_len name_len NAME]
其中NAME是一系列nlen字符,不含终止NULL。
对于每个数据块,将该块读入内存并使用dir_entry *dp指向加载的数据块。
然后使用name_len将NAME提取为字符串,并与name[0]进行比较。如果它们不匹配,则通过以下代码转到下一个dir_entry:
dp = (dir_entry *) ((char *)dp + dp->rec_len);
继续搜索。如果存在name[0],则可以找到它的dir_entry,从而找到它的索引节点号。

(6)

使用索引节点号ino来定位相应的索引节点。回想前面的内容,ino从1开始计数。使用邮差算法计算包含索引节点的磁盘块及其在该块中的偏移量。
blk=(ino - 1) / INODES_PER_BLOCK+ InodesBeginBlock;
offset = (ino - 1)% INODES_PER_BLOCK;
然后在索引节点中读取/a,从中确定它是否是一个目录(DIR)。
如果/a不是目录,则不能有/a/b,因此搜索失败。
如果它是目录,并且有更多需要搜索的组件,那么继续搜索下一个组件name[1]。
现在的问题是:在索引节点中搜索/a的name[1],与第(5)步完全相同。

(7)
由于(5)~(6)步将会重复n次,所以最好编写一个搜索函数:
u32 search ( INODE*inodePtr, char *name)
然后只需调用n次search函数
如果搜索循环成功结束,ip必须指向路径名的索引节点。

 

上一篇:C51汇编求最大值


下一篇:Python游戏开发,pygame模块,Python实现过迷宫小游戏