11-ext2 文件系统实验

上一篇讲解了太多的概念,估计你也看烦了。不如,动手练一练?

1. 总览

  • 环境配置部分

    • 安装一个 64MB 的空白硬盘
    • 格化化成 ext2 文件系统
    • 在这个文件系统里放几个文件。实验中存了 hello.txt, happy.txt, 一个目录,目录下面还有一个 main.c 文件
    • 把这个硬盘数据全部 dump 出来
  • 数据分析部分

    • 分析超级块结构
    • 分析 inode 表的位置
    • 分析 inode 2
    • 分析 hello.txt 的数据位置

2. 环境配置

2.1 安装空白硬盘

这里写图片描述

图1 添加新的硬件

这里写图片描述

图2 选择硬盘

这里写图片描述

图3 默认选项

这里写图片描述

图4 创建虚拟磁盘

这里写图片描述

图5 创建一个 64MB 大小的磁盘

这里写图片描述

图6 完成保存
至此,完成了硬盘的安装。这时候启动你的虚拟机,进入系统。

2.2 格式化成 ext2 文件系统

2.2.1 查看设备名

$ sudo fdisk -l

键入上条命令后,可以看到图7这样的信息。所以设备名是 /dev/sdb

这里写图片描述

图7 查看设备名

2.2.2 格式化 /dev/sdb

$ sudo mkfs -t ext2 /dev/sdb

完成后,使用下面的命令可以查看格式后的一些信息。

$ sudo dumpe2fs /dev/sdb

这里写图片描述

图8 查看设备信息
从图8中可以看到格式化后的一些信息,比如 block size 的大小为 1024 字节。

2.3 挂载磁盘

$ cd
$ mkdir bean
$ sudo mount /dev/sdb bean

上面这几行命令在用户目录下创建了一个文件夹 bean,并把磁盘挂载到了 bean 下。

如果你的 bean 目录所有者和用户组都是 root,使用下面的方法把它改成你自己的。

$ chown allen:allen bean -R

进入 bean 目录后,你可能会看见有一个 lost found 类似的文件夹,使用下面的方法把它删掉,以免给我们造成影响。

$ rm * -r

2.4 向磁盘写入文件

这里写图片描述

图9 向磁盘写入文件

使用 ll -i命令,可以查看到文件的 inode 节点编号。这里看到 hello.txt的 inode 节点编号是 11.

这里写图片描述

图10 查看 inode 编号

2.5 卸载磁盘

这一步必须做。尽管你向磁盘创建了几个文件,但是,linux 操作系统底层还存在磁盘缓冲的原因,数据并没有真正的写入磁盘。我尝试过 sync 命令,发现仍然没有同步进去,暂时不知原因。不过卸载后,就一定会同步进去。

$ sudo umount bean

至此,环境已经创建完成。

3 数据分析

要想分析数据,首先要把磁盘数据 dump 出来。所谓的 dump 就是把磁盘里的 2 进制数据读出来保存到一个文件里去。

3.1 dump 磁盘数据

$ sudo hexdump -C /dev/sdb > sdb_content

通过上面的命令,可以把磁盘数据完整的写到 sdb_content 这个文件里去。结果如图 11.

这里写图片描述

图11 磁盘2进制数据预览

接下来,我们要做的就是分析这个文件里的数据。

3.2 超级块分析

这里写图片描述

图12 超级块

勘误:图 12 中结构体成员 s_wtime 对应的值是 57f9fb91,这里实际有误,正确的值是 s_wtime = 57f9fd99. 感谢网友 @song 指出。

图12 中右侧部分,就是超级块部分。为什么要从 0x00000400 开始呢?还记得上一篇讲过的 boot block 吗? 它始终要占用 1KB,而1KB就相当于 0x400 字节。

从上图中可以分析出,inode 的节点的个数是 0x00004000,block 有 0x00010000 个。如果你不信,你可以翻看图8进行对比。

s_log_block_size 记录的值是 0,为什么?实际上,block size 的计算公式是这样的:

b l o c k _ s i z e = 1024 × 2 s _ l o g _ b l o c k _ s i z e block\_size = 1024\times 2^{s\_log\_block\_size} block_size=1024×2s_log_block_size

这些在 linux 内核代码里都可以找到,这里就不搬上来了。

3.3 组描述符分析

这里写图片描述

图13 组描述符
组描述符是一个数组,英文写为 GDT(此 GDT 不是 cpu 保护模式中那个存入段描述符的GDT,不要搞混)。

GDT 中的每个元素占用 32 字节,相对于图13中右侧部分就是两行。

图13展示了这个GDT表中存放了8个描述符。不过,我们只关心第0个描述符,即GDT[0]。它的值在图13中已经全部标识。想一想,上面的偏移值是怎么算出来的?

图14 给出了block位图和inode位图,它们的作用就是记录哪些 block 和 inode 编号被占用。

这里写图片描述

图14 block 位图和 inode 位图

最重要的是 inode 表,它们于第 0x00000104 个磁盘块上。每个磁盘块大小是 0x400 B(1KB),所以 inode 表的偏移是
i n o d e _ t a b l e _ o f f s e t = 0 x 104 × 0 x 400 = 0 x 00041000 inode\_table\_offset = 0x104\times0x400 = 0x00041000 inode_table_offset=0x104×0x400=0x00041000

3.4 inode 表分析

分析了 inode 表的位置后,把它找出来看看。见图15.

这里写图片描述

图15 inode 表

inode 表中的每个元素占用 128 个字节。也就是 0x80 字节。注意 inode 的编号不是从 0 开始,而是 1.计算的时候需要小心换算。

在 linux 系统设计中,inode 编号为 2 的节点,永远都是磁盘根目录。

3.5 inode 2 分析

还记得我们刚刚在 /dev/sdb 根中写的几个文件吗?分别是 hello.txt, happy.txt, mydir。如果我们发现 inode 2 记录了这些数据,证明我们的分析是没问题的。

在 inode 数据结构中,偏移为 0x28 的位置有个成员i_block[EXT2_N_BLOCKS](EXT2_N_BLOCKS 在源码中被宏定义为 15),这个成员,它记录了数据所在的磁盘块的位置。

图15中我们可以看到 inode 2 中的成员 i_block[0] = 0x00000204,其它值都是 0. 我们找到 inode 2记录的数据位置,如图 16.

这里写图片描述

图16 目录项

因为 inode 2 记录的是根目录的数据,根目录数据的组织形式是一个个的 dir_entry,它的结构在图16中左侧给出。从图16 右侧对比可以看到,这里一共有 5 个 dir_entiry。为什么是 5 个,不是 3 个?

不要忘记还有两个隐藏目录,分别是 ...,即当前目录和上层目录

3.6 hello.txt 分析

这里写图片描述

图17 查看 hello.txt 的 inode 编号

按照dir_entry 结构体的定义,我们可以看到 hello.txt 的 inode 节点号是 0x0000000b,也就是 11.

接下来,我们再回到 0x00041000 的位置查看 inode 表的第 11 项,图18。

这里写图片描述

图18 查看 inode 11 的内容

可以分析出 hello.txt 数据的位置在 0x00100400 这个地方,接下来跳到这个位置去看看。

这里写图片描述

图19 inode 11 索引出的数据块

和预期一样,正是我们之前写入的数据。

4. 总结

本篇深入分析了 ext2 文件系统的细节,演示了如何去查找 hello.txt 的位置。相信你对 inode 有了更深刻的认识。

当然,你知道我还写入了 happy.txt,以及另外一个目录 mydir,这个目录下还有一个文件 main.c。小伙伴们,你们能按图索骥,找出这些文件在哪吗?

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值