天天看點

Busybox initrd及初始化流程

Initrd檔案系統加載流程:

    1. 引導加載程式,例如 GRUB,定義了要加載的核心,并将這個核心映像以及相關的 initrd 拷貝到記憶體中。我們可以在 Linux核心源代碼目錄中的 ./init 子目錄中找到很多這種功能。

    2. 在核心和 initrd映像被解壓并拷貝到記憶體中之後,核心就會被調用了。它會執行不同的初始化操作,最終會發現自己到了init/main.c:init()(subdir/file:function)函數中。

    3. 這個函數執行了大量的子系統初始化操作。此處會執行一個對init/do_mounts.c:prepare_namespace() 的調用,這個函數用來準備名稱空間(挂載 dev檔案系統、RAID或 md、裝置以及最後的 initrd)。

    4. 加載 initrd 是通過調用init/do_mounts_initrd.c:initrd_load() 實作的。

    5. initrd_load()函數調用了init/do_mounts_rd.c:rd_load_image(),它通過調用init/do_mounts_rd.c:identify_ramdisk_image() 來确定要加載哪個RAM磁盤。

    6. 這個函數會檢查映像檔案的 magic 号來确定它是 minux、etc2、romfs、cramfs 或 gzip 格式。

    7. 在傳回到initrd_load_image 之前,它還會調用 init/do_mounts_rd:crd_load()。這個函數負責為 RAM磁盤配置設定空間,并計算循環備援校驗碼(CRC),然後對 RAM磁盤映像進行解壓,并将其加載到記憶體中。

    8. 現在,我們在一個适合挂載的塊裝置中就有了這個 initrd 映像。

    9. 現在使用一個 init/do_mounts.c:mount_root()調用将這個塊裝置挂載到根檔案系統上。它會建立根裝置,并調用 init/do_mounts.c:mount_block_root()。

    10. 在這裡調用init/do_mounts.c:do_mount_root(),後者又會調用 fs/namespace.c:sys_mount()來真正挂載根檔案系統,然後 chdir 到這個檔案系統中。

    11. 最後,傳回到 init 函數中,并調用init/main.c:run_init_process。這會導緻調用 execve 來啟動 init 程序(在本例中是/linuxrc)。linuxrc 可以是一個可執行程式,也可以是一個腳本(條件是它有腳本解釋器可用)。

Busybox init程式執行的順序如下:

   1. 建立init的信号處理

 2. 初始化控制台

 3. 分析inittab檔案,/etc/inittab

 4. 執行系統初始化腳本,/etc/init.d/rcS

 5. 執行所有inittab中類型為wait的程式

 6. 執行所有inittab中類型為once的程式

 7. 完成以上步驟後,init循環執行所有inittab中類型為respawn和askfirst的程式。

Busybox inittab檔案示例:

::sysinit:/etc/init.d/rcS

# /sbin/getty respawn shell invocations for selected ttys.
tty1::respawn:/sbin/getty -nl /sbin/autologin 38400 tty1
tty2::askfirst:/sbin/getty 38400 tty2
tty3::askfirst:/sbin/getty 38400 tty3
#tty4::askfirst:/sbin/getty 38400 tty4
#tty5::askfirst:/sbin/getty 38400 tty5
#tty6::askfirst:/sbin/getty 38400 tty6

# Stuff to do when restarting the init
# process, or before rebooting.
::restart:/etc/init.d/rc.shutdown
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/etc/init.d/rc.shutdown
           

Busybox inittab檔案解釋:

/etc/inittab 檔案中每個條目用來定義一個子程序,并确定它的啟動方法,格式如下 :

<id>:<runlevels>:<action>:<process>

例如:

ttySAC0:askfirst:-/bin/sh

(1)<id>:表示這個程序要使用的控制台(即标準輸入、标準輸出、标準錯誤裝置)。如果省略,則使用與init程序一樣的控制台。

(2)<runlevels>:對于Busybox init程式,這個字段滑意義,可以省略。

(3)<action>:表示init程式如何控制這個子程序,

(4)<process>: 要執行的程式,它可以是可執行程式,也可以是腳本

如果<process>:字段有"-"字元,表示這個程式被稱為“互動的”。在/etc/inittab/檔案的控制下,init程序的行為總結如下:

(1)在系統啟動前期,init程序首先啟動<action>為sysinit wait once的3類子程序。

(2)在系統正常運作期間,init程式首先啟動,<action>為respawn askfirst的兩類子程序,并監視它們,發現某個子程序退出時重新啟動它。

(3)在系統退出時,執行<action> 為shutdown restart ctrlaltdel的3類子程序之一或全部。

Action           執行條件                             說明

Sysinit          系統啟動後最先執行            隻執行一次,init程序等待它結束才繼續執行其它動作

Wait             系統執行完sysinit程序後      隻執行一次,init程序等待它結束才繼續執行其它動作

Once            系統執行完wait程序後         隻執行一次,init程序不等待它結束

Respawn      啟動完once程序後               Init程序監測發現子程序退出時,重新啟動它

Askfirst         啟動完respawn程序後         與respawn類似,不過init程序先輸出“ Please press Enter to actvie this console ”,等使用者輸入駕車鍵之後才啟動子程序

Shutdown     當系統關機時                        即重新開機關閉系統指令時

Restart          Busybox中配置了CONFIG_FEATURE_USE_INITTAB,并且init程序接收到SIGHUP信号時    先重新讀取,解析/etc/inittab檔案,再執行 restart 程式

Ctrlatldel       按下 Ctr+Alt+del 組合鍵時

繼續閱讀