文章目录
系列博文
Linux文件系统:minix文件系统二进制分析1(格式化)
Linux文件系统:minix文件系统二进制分析3(硬链接与软链接)
Linux文件系统:minix文件系统二进制分析4(rm删除)
1. minix文件系统二进制分析1:刚刚格式化后的文件系统
工作几年来,用过不少文件系统,甚至手把手移植和裁剪过Fatfs文件系统,但是却对文件系统内部的存储方式和玩儿法一直一无所知,于是决定好好把文件系统的运行机制好好研究研究,但是现存文件系统的类型百花齐放,各有千秋,还是决定从minix文件系统入手,这是早期在minix系统上用的一种简单的文件系统,所谓麻雀虽小五脏俱全,正好可以做来了解文件系统之用,从而洞察后来更加复杂的文件系统,万变不离其宗,深入剖析了minix文件系统,理解其他类型的文件系统也就举一反三手到擒来了。
1.1 创建硬盘
既然要研究文件系统,首先我们得找一个u盘,翻了翻我封印已久的抽屉,竟然找不到一个U盘,幸好虚拟机这项技术的出现方便了像我这样舍不得花钱买U盘的人…
我们能在Windows系统下的VmWare中安装一个Ubuntu系统,更何况虚拟一个硬盘?本章将在虚拟机里创建一个16M的硬盘作为起点,来一步一步分析minix文件系统。
1.1.1 添加一个16M的块设备
在Ubuntu虚拟机中添加一个大小为16M的块设备,此时还没有将其进行文件系统格式化
1.1.2 格式化块设备
在终端输入 fdisk -l指令查看所有块设备信息,可以找到 /dev/sdb设备即为上一步骤创建的硬盘。
格式化硬盘为minix文件系统
根据格式化后的信息,我们可以知道,硬盘上的minix文件系统一共有5472个inodes,也就是说最多能在上面创建5472个文件,一共16384个数据块,Firstdatazone=176 表示第一个node节点位于第176个块,Maxsize表示每个文件支持的最大长度。
接下来,我们使用hexdump -C /dev/sdb > minix_orig.dat 将硬盘的2进制数据dump出来,如下图所示,特备强调,此时的minix文件系统只有一个根目录,其他什么都没有,干干净净。
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000400 60 15 00 40 01 00 02 00 b0 00 00 00 00 1c 08 10 |`..@............|
00000410 8f 13 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000800 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000aa0 00 00 00 00 00 00 00 00 00 00 00 00 fe ff ff ff |................|
00000ab0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000c00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000013e0 00 00 00 00 00 00 00 00 00 00 fe ff ff ff ff ff |................|
000013f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00001400 ed 41 00 00 40 00 00 00 88 09 a1 61 00 02 b0 00 |.A..@......a....|
00001410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
0002c000 01 00 2e 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0002c010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0002c020 01 00 2e 2e 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0002c030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
01000000
1.2 minix文件系统的存储结构
minix文件系统的存储结构分为五大部分,其他类型的文件系统也是大同小异
1.2.1 超级块
超级块代表了整个文件系统,超级块是文件系统的控制块,有整个文件系统信息,在格式化操作完成后,超级块的信息基本就已经定型了,可以说,一个超级块就代表了一个文件系统。
值得一提的是,当我们在linux终端mount某个块设备时,内核会读取超级块的信息,完成文件系统的挂载。
1.2.1.1 linux中超级块数据结构
内核挂载文件系统时,先去获得超级块的信息并保存在内核数据结构中
/*
* minix super-block data on disk
*/
struct minix_super_block {
__u16 s_ninodes;
__u16 s_nzones;
__u16 s_imap_blocks;
__u16 s_zmap_blocks;
__u16 s_firstdatazone;
__u16 s_log_zone_size;
__u32 s_max_size;
__u16 s_magic;
__u16 s_state;
__u32 s_zones;
};
元素 | 十六进制 | 十进制 | 含义 |
---|---|---|---|
s_ninodes | 0x1560 | 5472 | 一共5472个inode节点 |
s_nzones | 0x4000 | 4096 | 一共16384个 data block |
s_imap_blocks | 0x0001 | 1 | inode位图占用1个block |
s_zmap_blocks | 0x0002 | 2 | data block位图占据2个block |
s_firstdatazone | 0x00b0 | 176 | 第一个data block的编号为176 |
s_log_zone_size | 0x0000 | 0 | 一个data block占用2的0次方K,即1K |
s_max_size | 0x10081c00 | 268966912 | 文件最大长度为268966912字节 |
s_magic | 0x138f | minix文件系统的魔幻数 | |
s_state | 0x0001 | 文件系统当前状态,0为已挂载,1为未挂载 | |
s_zones | 0x0000 |
1.2.2 inode节点
1.2.2.1 内核数据结构
如下图所示,内核中的struct minix_inode数据结构也是minix文件系统inode节点信息在存储介质中的存储方式,接下来我们对照dump文件中的数据,来看一下inode的值。
/*
* This is the original minix inode layout on disk.
* Note the 8-bit gid and atime and ctime.
*/
struct minix_inode {
__u16 i_mode;
__u16 i_uid;
__u32 i_size;
__u32 i_time;
__u8 i_gid;
__u8 i_nlinks;
__u16 i_zone[9];
};
1.2.2.2 万物之源No1节点—根目录
当用户执行vim /dirdemo/filelevel2.txt操作时,在文件系统中是如何找到filelevel2.txt文件,并将其内容显示出来的呢?
太极生两仪,两仪生四象,四象生八卦,宇宙再大,最开始也是从一个点,任何事物都有其起源,文件系统的起点便是从根目录开始,所以在我们格式化硬盘之后,inode节点只有一个,那就是表示根目录的inode节点。
在超级块的属性当中有一个s_firstdatazone属性,该值作为查找文件的门户,其指向的是根目录的数据区,174x1024=0x2c000。
在文件系统的inode区,第一个inode节点便是根目录节点,如下图所示。
关于minix文件系统中,inode的各个属性,linux内核定义了下述结构体类型进行存储。
属性 | 值Hex | 值DEC | 含义 |
---|---|---|---|
i_mode | 0x41ed | 文件类型和读写权限 | |
i_uid | 0x0000 | 用户root | |
i_size | 0x00000040 | 大小 | |
i_time | 0x61a10988 | 最后一次修改时间 | |
i_gid | 0x00 | 用户组root | |
i_nlinks | 0x02 | 被2个文件所引用(分别是.和…) | |
i_zone | 0x00b0 | 176 | 数据在第176个data block上(1024x176 = 0x2c000) |
1.2.3 第一个数据块
No1节点的i_zone指向了地址0x2c000,接下来我们看一下0x2c000地址处存放的数据,如下图红框所示,前两行是对链接’.‘的目录描述,其指向的inode节点编号为1,即根目录,后两行是对目录’…'的描述,它也指向inode 1节点。