2008年10月21日 星期二

init的正常啟動流程

所有user space processes的祖先process "init"的從核心(另一種從initramfs方式去啟動)正常啟動流程如下:

1. 核心中的start_kernel() (在linux-2.6.27/init/main.c)-> rest_init()->kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND)-> init_post(),init_post()會做以下的檢查:

run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");

若上述檢查失敗則可透過grub 設定kernel cmline 變數"init" 例如:init=/sbin/your_init

2.一但 "1."找到init程式,就執行之其執行流程如下所述:

mian()->init_main(dfl_level)//dfl_level=0, init_main()所做的事如下:

runlevel = '#';//代表目前的runlevel ,系統啟動時runlevel 為"#"
read_inittab(); //讀取/etc/inittab,將其內容存入全域變數structure CHILD * family,將runlevel 為"#"與 //action "sysinit"做對應
start_if_needed(); // Walk through the "family" list and start up children. 由於系統啟動時runlevel //為"#"會執行對應action "sysinit" 的process "/etc/init.d/rcS"
while(1){
boot_transitions(); //將runlevel從"#"轉換到"/etc/inittab" 描述的"default runlevel"
check_init_fifo(); //check FIFO file "/dev/initctl"是否有request發生,系統剛啟動request是空的且建立一個FIFO file "/dev/initctl"
fail_check();
process_signals();// Init got hit by a signal. See which signal it is, and act accordingly.
start_if_needed();//執行於runlevel 為"default runlevel"的process group,以default的"/etc/ //inittab"為例default runlevel為2所以會執行"/etc/init.d/rc 2"
}

3. 由於init 在init_main loop會不斷檢FIFO file "/dev/initctl' 是否有其他process 透過該file轉換目前的runlevel ( check_init_fifo()) 若有就將新的runlevel設定給目前的runlevel(fifo_new_level()) 當執行到start_if_needed()就會執行以新runlevel為代表的process group,以系統關機指令shutdown為例,其實它是呼叫"init 0" 將系統由目前的runlevel轉換到runlevel 0,所以會執行"/etc/init.d/rc 0"

參考資料:
http://72.14.235.104/search?q=cache:df24chyWw54J:blogimg.chinaunix.net/blog/upfile2/080802120641.pdf+TELINIT_USES_INITLVL&hl=zh-TW&ct=clnk&cd=2&gl=tw&client=firefox-a#21

沒有留言: