看了几天《深入理解linux内核》的ext2文件系统部分和VFS部分,稍微了解了点文件在内存中的存储结构,但是总是弄不清楚在硬盘上实际的存储方式,特别是文件夹的存储。
保存文件夹的结构很简单,没有这个文件夹下所有文件的索引,看了几遍书,都不能理解在硬盘上文件夹结构的存储,只能根据网上的例子自己跟着做实验。(过程参考了http://blog.chinaunix.net/u1/48373/showart_1210707.html的博客)
首先显示要分配一个空间,格式化为ext2分区,并在这个空间上进行文件和文件夹的操作。
dd if=/dev/zero of=disk bs=1M count=1 #创建1MB的空间,并填充为0
mkfs.ext2 disk #格式化为ext2分区,从输出信息中可以看见block大小为1024byte
mount -o loop disk /mnt/ #挂载分区
然后进入挂载的目录,开始创建文件和文件夹。
test.txt(内容为hello)
创建test1.txt(内容为hello1)
创建文件夹test
在文件夹test中,创建文件test2.txt(内容为hello2)
创建文件test3.txt(内容为hello3)
然后就可以卸载这个文件,用16进制编辑器打开disk文件,查看ext2的文件保存格式。
打开disk文件后,跳转到地址0x800处(开头第一块保留为引导块,后面一块为块组0的超级块),即块组0的组描述符处。
根据组描述符的结构,在第9个字节开始是第一个索引节点表块的块号。从这开始的4个字节(均为little-endian),就是第一个索引节点表块的块号。这里是8。根据计算可知,它的16进制地址是0x2000。
因为文件系统的根目录总是在索引节点的第二个,每个索引节点大小是固定的,为128字节(0x80)。即地址0x2080就是根目录的索引节点(inode)。根据索引节点的结构,可以找到根目录数据块编号为0x18,也就是地址0x6000。
在0x6000处,可以看见根目录下创建的所有目录和文件。也就是说,ext2的文件夹结构ext2_dir_entry_2中保存的内容,不是文件夹本身,而是文件夹中的所有文件的信息(包括目录),其中的第一个inode字段,是这个文件(文件夹)所在的索引节点编号。
这里找到的除了刚刚创建的一个文件夹和一个文件之外,还有文件系统创建的时候自动产生的lost+find文件夹和.和..文件夹(分别表示本文件夹和父文件夹)。通过目录结构的第一个字段,可以找到想要寻找的文件(文件夹)所在的inode,然后去索引节点表中寻找这个节点,并找到这个节点的数据存储位置(i_blocks字段),再计算分配到的block的地址,读取实际的数据。
根据目录的结构查找,找到test.txt的索引节点偏移量是0x0D。那么,test.txt的索引节点地址是0x2000+0x80*(0x0D-0x01)=0x2600。在该处找到数据块的指针为0x27(地址0x9C00)。
转到0x9C00,就可以看见里面的数据hello。