2.2. 实例剖析 请点评
如果要格式化一个分区来研究文件系统格式则必须有一个空闲的磁盘分区,为了方便实验,我们把一个文件当作分区来格式化,然后分析这个文件中的数据来印证上面所讲的要点。首先创建一个1MB的文件并清零:
$ dd if=/dev/zero of=fs count=256 bs=4K 我们知道cp命令可以把一个文件拷贝成另一个文件,而dd命令可以把一个文件的一部分拷贝成另一个文件。这个命令的作用是把/dev/zero文件开头的1M(256×4K)字节拷贝成文件名为fs的文件。刚才我们看到/dev/zero是一个特殊的设备文件,它没有磁盘数据块,对它进行读操作传给设备号为1, 5的驱动程序。/dev/zero这个文件可以看作是无穷大的,不管从哪里开始读,读出来的都是字节0x00。因此这个命令拷贝了1M个0x00到fs文件。if和of参数表示输入文件和输出文件,count和bs参数表示拷贝多少次,每次拷多少字节。 做好之后对文件fs进行格式化,也就是把这个文件的数据块合起来看成一个1MB的磁盘分区,在这个分区上再划分出块组。
$ mke2fs fs mke2fs 1.40.2 (12-Jul-2007) fs is not a block special device. Proceed anyway? (y,n) (输入y回车) Filesystem label= OS type: Linux Block size=1024 (log=0) Fragment size=1024 (log=0) 128 inodes, 1024 blocks 51 blocks (4.98%) reserved for the super user First data block=1 Maximum filesystem blocks=1048576 1 block group 8192 blocks per group, 8192 fragments per group 128 inodes per group Writing inode tables: done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 27 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override. 格式化一个真正的分区应该指定块设备文件名,例如/dev/sda1,而这个fs是常规文件而不是块设备文件,mke2fs认为用户有可能是误操作了,所以给出提示,要求确认是否真的要格式化,输入y回车完成格式化。
现在fs的大小仍然是1MB,但不再是全0了,其中已经有了块组和描述信息。用dumpe2fs工具可以查看这个分区的超级块和块组描述符表中的信息:
$ dumpe2fs fs dumpe2fs 1.40.2 (12-Jul-2007) Filesystem volume name:
用常规文件制作而成的文件系统也可以像磁盘分区一样mount到某个目录,例如:
$ sudo mount -o loop fs /mnt $ cd /mnt/ $ ls -la total 17 drwxr-xr-x 3 akaedu akaedu 1024 2008-10-25 12:20 . drwxr-xr-x 21 root root 4096 2008-08-18 08:54 .. drwx------ 2 root root 12288 2008-10-25 12:20 lost+found -o loop选项告诉mount这是一个常规文件而不是一个块设备文件。mount会把它的数据块中的数据当作分区格式来解释。文件系统格式化之后在根目录下自动生成三个子目录:.,..和lost+found。其它子目录下的.表示当前目录,..表示上一级目录,而根目录的.和..都表示根目录本身。lost+found目录由e2fsck工具使用,如果在检查磁盘时发现错误,就把有错误的块挂在这个目录下,因为这些块不知道是谁的,找不到主,就放在这里“失物招领”了。
现在可以在/mnt目录下添加删除文件,这些操作会自动保存到文件fs中。然后把这个分区umount下来,以确保所有的改动都保存到文件中了。
$ sudo umount /mnt 注意,下面的实验步骤是对新创建的文件系统做的,如果你在文件系统中添加删除过文件,跟着做下面的步骤时结果可能和我写的不太一样,不过也不影响理解。 现在我们用二进制查看工具查看这个文件系统的所有字节,并且同dumpe2fs工具的输出信息相比较,就可以很好地理解文件系统的存储布局了。
$ od -tx1 -Ax fs 000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 000400 80 00 00 00 00 04 00 00 33 00 00 00 da 03 00 00 000410 75 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ... 其中以*开头的行表示这一段数据全是零因此省略了。下面详细分析od输出的信息。
从000000开始的1KB是启动块,由于这不是一个真正的磁盘分区,启动块的内容全部为零。从000400到0007ff的1KB是超级块,对照着dumpe2fs的输出信息,详细分析如下: 图 29.3. 超级块
超级块中从0004d0到末尾的204个字节是填充字节,保留未用,上图未画出。注意,ext2文件系统中各字段都是按小端存储的,如果把字节在文件中的位置看作地址,那么靠近文件开头的是低地址,存低字节。各字段的位置、长度和含义详见[ULK]。
从000800开始是块组描述符表,这个文件系统较小,只有一个块组描述符,对照着dumpe2fs的输出信息分析如下:
... Group 0: (Blocks 1-1023) Primary superblock at 1, Group descriptors at 2-2 Reserved GDT blocks at 3-5