init実行
久しぶりにxv6の処理を読んでいる。
コンパクトなコードでここまで処理を実装しているのは凄いの一言に尽きるが、特に気になったinitに関してメモ。
initcode.S(_binary_initcode_start)
initcode.sは仮想アドレス0x00000000に配置されている。
非常に単純なアセンブラ で記述されており、処理内容は以下の2つである。
1. fs.img上のinitを実行(syscall exec)する。
2. initcode自身を終了(sys call exit)する。
# exec(init, argv)
.globl start
start:
pushl $argv
pushl $init
pushl $0 // where caller pc would be
movl $SYS_exec, %eax
int $T_SYSCALL
# for(;;) exit();
exit:
movl $SYS_exit, %eax
int $T_SYSCALL
jmp exit
# char init = "/init\0";
init:
.string "/init\0"
# char *argv = { init, 0 };
.p2align 2
argv:
.long init
.long 0
init.c(init)
fork(sys call fork)を実行する。
親プロセス側は子プロセスの終了待ち。
子プロセス側はshell(sh.c)を実行する。
int main(void) { int pid, wpid; if(open("console", O_RDWR) < 0){ mknod("console", 1, 1); open("console", O_RDWR); } dup(0); // stdout dup(0); // stderr for(;;){ printf(1, "init: starting sh\n"); pid = fork(); if(pid < 0){ printf(1, "init: fork failed\n"); exit(); } if(pid == 0){ exec("sh", argv); printf(1, "init: exec sh failed\n"); exit(); } while*1 >= 0 && wpid != pid) printf(1, "zombie!\n"); } }
*1:wpid=wait(