前段时间做linux虚拟化相关的项目,需要实现一个功能,通过linuxExt3\4文件系统中文件的inode号,计算出该文件在linux文件系统的磁盘块号(blocks)以及扇区号(sectors),基本上算是对linux的EXT文件系统有了较深的理解。这样的一个工作,花费了我很长的时间,网上只是关于文件系统的资料比较多,但牵扯到具体的计算,基本上没有资料。因此,我想在这里,把自己前一段时间的工作成果分享出来,或许能给以后在这方面研究的朋友们一些帮助。
在介绍EXT文件系统之前,我想先对文件的inode号进行一下说明。
文件存储在硬盘上,硬盘的最小存储单位叫做扇区(sector)。每个扇区的大小不一,常见512KB。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个 sector组成一个 block。文件数据就存放在磁盘块中,inode作为文件的元信息,存储则文件创建者,创建日期,大小,读写权限等。每个文件对应一个唯一inode号。
每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。
可以看出来,这里的数字全是以16进制进行的。跟我们之前分析的文件系统磁盘结构一样,刚开始有1000字节的空白,代表的是启动块。从第0X400(即第1000字节)开始,就到了第一个块组的范围,第一个块组的头部是超级块,也就是说,从0X400开始,就是第一个超级块。前四个字节是01cee000=30334976(之前说过的小端序),这四个字节代表的是inode count,inode的个数,可以看出来,与刚才在块组信息里面的inode个数一致;接下来四个字节是block count总块数,0X073b0b00=121309952,同样和之前的块组信息里面的总块数一致。这里我只是给大家提供一种方法,如何找到文件系统的数据结构中的各个字段,下面还有很多,朋友们可以自行验证找到所有字段来获取想要得到的信息。需要注意的是各个字段的长度。
Group Descriptor Tabel 每个块组都有一个专门的数据结构用来描述整个块组的相关信息,即块组描述表,它紧跟在超级块后面的一个块,其每一项称为组描述符,是一个大小为32字节的数据结构。记录组中块位图所在的块号、索引节点位图所在的块号、索引节点表的第一个块号等。
块组描述符的数据结构如下图:
还是从之前的块组信息中看到 :Primary superblock at 0, Group descriptors at 1-29,第二块就是快组描述符的位置了。由于每个块大小为4096字节,所以在0x1000开始为第二块,即快组描述符的开始。
这样我们可以对照数据结构,在这些字节码中,找到需要的信息。
Block Bitmap 即此块组中的块位图,记录此组中的哪些块已经被占用,在分配块时使用。
Inode Bitmap 即此块组中的索引节点位图,记录本组中的哪些索引节点已经被占用。
Inode Table 即此块组中的索引节点表,每一项是一个文件的索引,即Inode,记录此文件的相关信息,其中本文最为关心的是地41~100字节,记录着文件所占数据库的信息。
Data Blocks 即此块组中的数据块,可供分配给各个文件使用。
在这篇文章中说明了如何查找文件系统中的相关信息的数据结构,接下来探讨如何通过inode计算出文件所在的磁盘块号和扇区号。