ビルドプロセスの中に、mkfsによりファイルシステムfs.imgを作る工程がある。
./mkfs fs.img README _cat _echo _forktest _grep _init _kill _ln _ls _mkdir _rm _sh _stressfs _usertests _wc _zombie
fs.imgはどのような仕組みで作られているんだろうか。まずは、こちらの解説が詳しい。
ブロックは1ブロック512バイトで構成されている。
- 0ブロック目は利用されていない。これは前回ブログで1ブロック分ブートに使用するので入っていないのかな?(でも向こうはxv6.imgだしなあ。。。)
- 1ブロック目はスーパーブロックとなっている。スーパーブロックの構成は、
struct superblock { uint size; // Size of file system image (blocks) uint nblocks; // Number of data blocks uint ninodes; // Number of inodes. uint nlog; // Number of log blocks uint logstart; // Block number of first log block uint inodestart; // Block number of first inode block uint bmapstart; // Block number of first free map block };
まずは、FSSIZE分のセクタのフォーマットをする。
for(i = 0; i < FSSIZE; i++) wsect(i, zeroes); ... void wsect(uint sec, void *buf) { if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){ perror("lseek"); exit(1); } if(write(fsfd, buf, BSIZE) != BSIZE){ perror("write"); exit(1); } }
fsfdファイルポインタに対して、セクタ分の情報を書き込んでいる。 次に、セクタ1にsuperblockの情報を書き込む。
memset(buf, 0, sizeof(buf)); memmove(buf, &sb, sizeof(sb)); wsect(1, buf);
iallocで新しいinodeを割り当て、それをルートディレクトリとする。iappendの構造はちょっと複雑ですぐには読めない。でも、必要ブロック分、wsectを呼び出している感じがする。
rootino = ialloc(T_DIR); assert(rootino == ROOTINO); bzero(&de, sizeof(de)); de.inum = xshort(rootino); strcpy(de.name, "."); iappend(rootino, &de, sizeof(de));
さらに、必要なファイルやディレクトリを追加していっている。
for(i = 2; i < argc; i++){ assert(index(argv[i], '/') == 0); if((fd = open(argv[i], 0)) < 0){ perror(argv[i]); exit(1); } // Skip leading _ in name when writing to file system. // The binaries are named _rm, _cat, etc. to keep the // build operating system from trying to execute them // in place of system binaries like rm and cat. if(argv[i][0] == '_') ++argv[i]; inum = ialloc(T_FILE); bzero(&de, sizeof(de)); de.inum = xshort(inum); strncpy(de.name, argv[i], DIRSIZ); iappend(rootino, &de, sizeof(de)); while((cc = read(fd, buf, sizeof(buf))) > 0) iappend(inum, buf, cc); close(fd); }
最後に、ブロックを調整して終わりかな。
// fix size of root inode dir rinode(rootino, &din); off = xint(din.size); off = ((off/BSIZE) + 1) * BSIZE; din.size = xint(off); winode(rootino, &din); balloc(freeblock); exit(0);