ウォンツテック

そでやまのーと

OSを作ろう - ファイルシステム編

Linuxカーネルとmke2fsのソース(http://e2fsprogs.sourceforge.net/)を読みながらsodexのファイルシステム作成toolを修正中。inodeの0番目と1番目にはデータを入れるとまずそうなのでbootm.oとkernel.binはinode 3,4辺りに移行予定。


super blockとgroup descriptorとinodeをごにょごにょやってたらとりあえずmountは成功。でも/mntでlsとやるとext2_readdir errorが発生。root directoryの中身がおかしい模様。

小技

ファイルシステムをファイルで作成し、いちいちデバイスにddしてから確認するのが面倒くさいので以下のようにloopデバイスに割り当てます。

mount fsboot.bin /mnt -t ext2 -o loop=/dev/loop3

以前、root directoryのinode番号がEXT2_ROOT_INOで「2」と決めうちされているという事を書いたけど、どうやらLinux側ではinodeブロックの先頭から次の領域をroot directoryとして認識している模様。inode構造体が128byte(0x80byte)なのでinodeブロックの先頭を0x4000とすると0x4080がroot directoryとして認識されている。自分の認識ではここはinode番号「1」の領域かと思ってたけど。どっちが正しいんだろうか?


この疑問を解決するべく実際のファイルシステムをhexdumpする事にした。

# mke2fs -b 4096 /dev/sdb
# dd if=/dev/sdb of=ext2fs.bin
# hexdump ext2fs.bin
0004000 0000 0000 0000 0000 4cb1 466a 4cb1 466a
0004010 4cb1 466a 0000 0000 0000 0000 0000 0000
0004020 0000 0000 0000 0000 0000 0000 0000 0000
 *1181372850*
0004080 41ed 0000 1000 0000 4d04 466a 4cb1 466a
0004090 4cb1 466a 0000 0000 0000 0003 0008 0000
00040a0 0000 0000 0000 0000 000a 0000 0000 0000
00040b0 0000 0000 0000 0000 0000 0000 0000 0000
 *1181372851*
0004300 8180 0000 c000 0040 4cb1 466a 4cb1 466a
0004310 4cb1 466a 0000 0000 0000 0001 0008 0000
0004320 0000 0000 0000 0000 0000 0000 0000 0000
 *1181372852*
0004350 0000 0000 0000 0000 0000 0000 000f 0000
0004360 0000 0000 0000 0000 0000 0000 0001 0000
0004370 0000 0000 0000 0000 0000 0000 0000 0000
 *1181372853*
0004500 41c0 0000 4000 0000 4cb1 466a 4cb1 466a
0004510 4cb1 466a 0000 0000 0000 0002 0020 0000
0004520 0000 0000 0000 0000 000b 0000 000c 0000
0004530 000d 0000 000e 0000 0000 0000 0000 0000
0004540 0000 0000 0000 0000 0000 0000 0000 0000

root directoryのinode番号は2であり、先ほどの調査からどうやら0x4080(block size 4096の時)がroot inodeであるらしい事がわかっているので見てみる。すると最初の16bitが"41ed"とありこれはinode構造体の先頭メンバi_mode値であると思われるので8進数に直すと"40755"となる。これはdirectoryを示す"40000"とmodeを示す"755"の論理和である事がわかる。ではlost+foundはinode番号11だった(ls -i /mnt/lost+foudで確認)のでその先0x4500(0x4000 + 0x80 * (11-1))を見てみるとやはり"0x41c0"="040700"となり正しい値を示している。

結論としては「inode番号はinodeブロックの先頭を"1"とした値である。」事がわかった。

小技

zsh(bash)で数値をx進数を変換する方法

 % echo $( ( [#x] 数値 ) )
例
 % echo $( ([#8] 0x41ed) )
 8#40755
 ↑( )の間のスペースは要りません

$(())は電卓代りにも使ってます。

。。はてなの脚注記法どうにかならんだろうか。。