- 論壇徽章:
- 0
|
前面說(shuō)了我們使用genromfs工具可以生成romfs文件系統(tǒng),那其生成的映像的格式是什么?這就要探究romfs文件系統(tǒng)的本質(zhì)了。
1.romfs映像結(jié)構(gòu)使用genromfs生成的romfs格式映像中,文件或者目錄是順序存放,每個(gè)文件頭對(duì)齊在16字節(jié)邊界上,基本結(jié)構(gòu)如圖:
![]()
romfs映像開(kāi)始16字節(jié)對(duì)應(yīng)struct romfs_super_block結(jié)構(gòu)體,接下來(lái)為romfs映像的卷標(biāo)。上圖所示情況為卷標(biāo)小于16字節(jié),如果卷標(biāo)大于16字節(jié),則順序存放在romfs_super_block之后,并且對(duì)齊在16字節(jié)邊界上。緊隨卷標(biāo)之后的就是第一個(gè)文件的文件頭romfs_inode結(jié)構(gòu),共16字節(jié),之后就是文件名,也是16字節(jié)對(duì)齊,然后才是文件內(nèi)容。其中在每個(gè)文件的文件頭中的前4字節(jié)(不包括低4位)為下一個(gè)文件頭在romfs映像中的偏移。romfs正是這樣將整個(gè)文件組織在一起的。下面分別看romfs_super_block和romfs_inode結(jié)構(gòu)。
1.1 romfs超級(jí)塊結(jié)構(gòu)在linux內(nèi)核中,romfs超級(jí)塊結(jié)構(gòu)定義在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-",是用來(lái)識(shí)別romfs文件系統(tǒng)的。這兩個(gè)值被定義在內(nèi)核中:
#define ROMSB_WORD0 __mk4('-','r','o','m')
#define ROMSB_WORD1 __mk4('1','f','s','-')
(2)size域size域表示romfs映像可訪(fǎng)問(wèn)的大小。也就是最后一個(gè)文件的結(jié)束位置(以16字節(jié)對(duì)齊),比如:
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$
對(duì)于上面生成的rom.img映像,在rom.img內(nèi)最后一個(gè)文件為len.c,其文件頭偏移為0x60,文件名為len.c(小于16字節(jié)),文件大小為44字節(jié),由此我們可以計(jì)算出該rom.img可訪(fǎng)問(wèn)的大小為:
size = (0x60 + 16 + 16 + 44 ) / 0x10 * 0x10 + 0x10 = 0xb0
第一個(gè)16表示文件頭(struct romfs_inode結(jié)構(gòu))的大小,第二個(gè)16表示文件名占用的長(zhǎng)度。下面我們使用file命令驗(yàn)證計(jì)算是否正確:
niutao@niutao:~/romfs$ file rom.img
rom: romfs filesystem, version 1 176 bytes, named niutao.
niutao@niutao:~/romfs$
可以看到文件可訪(fǎng)問(wèn)大小正是b0字節(jié)(176 bytes)。當(dāng)然最好還是直接查看romf.img超級(jí)結(jié)構(gòu)中size的值(位于rom.img偏移0x8處):
![]()
可以看到其值正是0x000000b0。
從size的定義我們可以看到,其為_(kāi)_be32(unsigned int),所以理論支持的romfs映像最大為4G
(3)checksum域 接下來(lái)是checksum域。該域是用于校驗(yàn)文件的。使用的算法為checksum算法。簡(jiǎn)單的說(shuō)就是一種數(shù)據(jù)校驗(yàn)方式,早期用于數(shù)據(jù)傳輸中對(duì)數(shù)據(jù)正確性的校驗(yàn),其基本思想是將要校驗(yàn)的數(shù)據(jù)加起來(lái)作為校驗(yàn)碼,和數(shù)據(jù)一并發(fā)送給對(duì)方,在對(duì)方接收完數(shù)據(jù)后,將接收到的數(shù)據(jù)加起來(lái)和傳輸過(guò)來(lái)的校驗(yàn)碼比較,如果相等,則說(shuō)明數(shù)據(jù)是正確的,否則說(shuō)明傳輸錯(cuò)誤。可見(jiàn)這種校驗(yàn)方式是及其簡(jiǎn)單的。那么在romfs中是如何使用的呢?
在romfs中,使用checksum算法校驗(yàn)的數(shù)據(jù)最大為512字節(jié),這一點(diǎn)可以從romfs_fill_super函數(shù)的這段代碼看出:
if (romfs_checksum(rsb, min_t(int, sz, 512))) {
printk ("romfs: bad initial checksum on dev "
"%s.\n", s->s_id);
goto out;
}
比如我們現(xiàn)在要對(duì)romfs_super_block校驗(yàn),是將該結(jié)構(gòu)的所有數(shù)據(jù)每四字節(jié)轉(zhuǎn)化成整形,然后加起來(lái),看其是否為0。如果為0,則說(shuō)明數(shù)據(jù)正確,否則則發(fā)生了錯(cuò)誤。那怎樣保證該結(jié)構(gòu)的所有數(shù)據(jù)加起來(lái)就是0呢?這個(gè)就是通過(guò)checksum域調(diào)整的。我們知道要生成romfs映像,則需使用genromfs工具。該工具在生成romfs映像的時(shí)候,就計(jì)算好的了校驗(yàn)和。假如我們現(xiàn)在是要對(duì)romfs_super_block生成校驗(yàn)碼(checksum域的值),我們首先將該結(jié)構(gòu)的這一項(xiàng)設(shè)置為0,然后使用checksum算法將要校驗(yàn)的數(shù)據(jù)(romfs_super_block結(jié)構(gòu))加起來(lái),取其負(fù)數(shù),賦值給checksum域。這樣再使用checksum算法將romfs_super_block結(jié)構(gòu)的數(shù)據(jù)加起來(lái),則結(jié)果必然為0。
具體計(jì)算過(guò)程可以參見(jiàn)genromfs源碼的romfs_checksum函數(shù)和fixsum函數(shù)。這里還要說(shuō)明的一點(diǎn)是,對(duì)于romfs映像頭(romfs_super_block),其校驗(yàn)和是針對(duì)前512字節(jié)的(如果romfs可訪(fǎng)問(wèn)的大小沒(méi)有512字節(jié)(romfs_super_block->size checksum)是針對(duì)文件頭和文件名的校驗(yàn)和。
(4)name域 接下來(lái)的name域被定義為char name[0],如果我們使用sizeof(struct romfs_super_block),會(huì)發(fā)現(xiàn)name域不占空間,這樣寫(xiě)的好處是我們可以直接使用romfs_super_block->name來(lái)訪(fǎng)問(wèn)volume。但我們?yōu)槭裁床恢苯訉olume也作為romfs_super_block的一個(gè)域呢?一個(gè)原因是volume是一個(gè)長(zhǎng)度不固定的域,你可以給他任意長(zhǎng)度,如果放在romfs_super_block中,則勢(shì)必要對(duì)volume有一個(gè)限制,這樣就限制了整個(gè)文件系統(tǒng)的靈活性。另一個(gè)原因是由前一個(gè)原因直接導(dǎo)致的,也就是如果將其作為romfs_super_block的一個(gè)域,其勢(shì)必會(huì)有固定長(zhǎng)度,這樣在volume很短的使用,就造成了空間的浪費(fèi).
本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u2/73528/showart_1903687.html |
|