免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1414 | 回复: 0

ROMFS文件系统分析[三]ROMFS映像文件结构 [复制链接]

论坛徽章:
0
发表于 2009-04-18 22:01 |显示全部楼层

                   前面说了我们使用genromfs工具可以生成romfs文件系统,那其生成的映像的格式是什么?这就要探究romfs文件系统的本质了。
1.romfs映像结构使用genromfs生成的romfs格式映像中,文件或者目录是顺序存放,每个文件头对齐在16字节边界上,基本结构如图:

   romfs映像开始16字节对应struct romfs_super_block结构体,接下来为romfs映像的卷标。上图所示情况为卷标小于16字节,如果卷标大于16字节,则顺序存放在romfs_super_block之后,并且对齐在16字节边界上。紧随卷标之后的就是第一个文件的文件头romfs_inode结构,共16字节,之后就是文件名,也是16字节对齐,然后才是文件内容。其中在每个文件的文件头中的前4字节(不包括低4位)为下一个文件头在romfs映像中的偏移。romfs正是这样将整个文件组织在一起的。下面分别看romfs_super_block和romfs_inode结构。
1.1 romfs超级块结构在linux内核中,romfs超级块结构定义在include/linux/romfs_fs.h中,源代码为:
               
               
               
               
                /* On-disk "super block" */
struct romfs_super_block {
        __be32 word0;
        __be32 word1;
        __be32 size;
        __be32 checksum;
        char name[0];           /* volume name */
};
(1)word0和word1   word0和word1的值是固定的,分别为"-rom"和"1fs-",是用来识别romfs文件系统的。这两个值被定义在内核中:
#define ROMSB_WORD0 __mk4('-','r','o','m')
#define ROMSB_WORD1 __mk4('1','f','s','-')
(2)size域size域表示romfs映像可访问的大小。也就是最后一个文件的结束位置(以16字节对齐),比如:
niutao@niutao:~/romfs$ ls -l romtest
total 4
-rw-r--r-- 1 niutao niutao 44 2009-04-08 20:15 len.c
niutao@niutao:~/romfs$ genromfs -f rom.img -d romtest/ -v -V niutao
0    niutao               [0xffffffff, 0xffffffff] 37777777777, sz     0, at 0x0     
1    .                    [0x80e     , 0x18aada  ] 0040755, sz     0, at 0x20   
1    ..                   [0x80e     , 0x18aac6  ] 0040755, sz     0, at 0x40     [link to 0x20    ]
1    len.c                [0x80e     , 0x18aadb  ] 0100644, sz    44, at 0x60   
niutao@niutao:~/romfs$
对于上面生成的rom.img映像,在rom.img内最后一个文件为len.c,其文件头偏移为0x60,文件名为len.c(小于16字节),文件大小为44字节,由此我们可以计算出该rom.img可访问的大小为:
size = (0x60 + 16 + 16 + 44 ) / 0x10  * 0x10 + 0x10 = 0xb0
第一个16表示文件头(struct romfs_inode结构)的大小,第二个16表示文件名占用的长度。下面我们使用file命令验证计算是否正确:
niutao@niutao:~/romfs$ file rom.img
rom: romfs filesystem, version 1 176 bytes, named niutao.
niutao@niutao:~/romfs$
可以看到文件可访问大小正是b0字节(176 bytes)。当然最好还是直接查看romf.img超级结构中size的值(位于rom.img偏移0x8处):

可以看到其值正是0x000000b0。
    从size的定义我们可以看到,其为__be32(unsigned int),所以理论支持的romfs映像最大为4G
(3)checksum域   接下来是checksum域。该域是用于校验文件的。使用的算法为checksum算法。简单的说就是一种数据校验方式,早期用于数据传输中对数据正确性的校验,其基本思想是将要校验的数据加起来作为校验码,和数据一并发送给对方,在对方接收完数据后,将接收到的数据加起来和传输过来的校验码比较,如果相等,则说明数据是正确的,否则说明传输错误。可见这种校验方式是及其简单的。那么在romfs中是如何使用的呢?
   在romfs中,使用checksum算法校验的数据最大为512字节,这一点可以从romfs_fill_super函数的这段代码看出:
if (romfs_checksum(rsb, min_t(int, sz, 512))) {
       printk ("romfs: bad initial checksum on dev "
                      "%s.\n", s->s_id);
       goto out;
}
比如我们现在要对romfs_super_block校验,是将该结构的所有数据每四字节转化成整形,然后加起来,看其是否为0。如果为0,则说明数据正确,否则则发生了错误。那怎样保证该结构的所有数据加起来就是0呢?这个就是通过checksum域调整的。我们知道要生成romfs映像,则需使用genromfs工具。该工具在生成romfs映像的时候,就计算好的了校验和。假如我们现在是要对romfs_super_block生成校验码(checksum域的值),我们首先将该结构的这一项设置为0,然后使用checksum算法将要校验的数据(romfs_super_block结构)加起来,取其负数,赋值给checksum域。这样再使用checksum算法将romfs_super_block结构的数据加起来,则结果必然为0。
    具体计算过程可以参见genromfs源码的romfs_checksum函数和fixsum函数。这里还要说明的一点是,对于romfs映像头(romfs_super_block),其校验和是针对前512字节的(如果romfs可访问的大小没有512字节(romfs_super_block->size checksum)是针对文件头和文件名的校验和。
(4)name域   接下来的name域被定义为char name[0],如果我们使用sizeof(struct romfs_super_block),会发现name域不占空间,这样写的好处是我们可以直接使用romfs_super_block->name来访问volume。但我们为什么不直接将volume也作为romfs_super_block的一个域呢?一个原因是volume是一个长度不固定的域,你可以给他任意长度,如果放在romfs_super_block中,则势必要对volume有一个限制,这样就限制了整个文件系统的灵活性。另一个原因是由前一个原因直接导致的,也就是如果将其作为romfs_super_block的一个域,其势必会有固定长度,这样在volume很短的使用,就造成了空间的浪费.


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/73528/showart_1903687.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP