|
最近研究lkml上的fastboot patch,再次意識到自己對initrd一直很迷茫 ,就大概花了天時間看了看這方面的文檔和代碼,備忘總結下。
不想長篇大論 ,簡單的說,主要有4種情況。1。無initrd 2。cpio initrd,于內核編在一起。 3。cpio initrd于內核分開編 4。 ramdisk initrd。
1。對于無initrd的情況,會先在initcall中調用default_rootfs(),隨后在prepare_namespace()中調用
mount_root掛載真實的文件系統 ,最后在init_post()中通過kernel_execve執(zhí)行根文件系統中的 /sbin/init。
2。對于后面3種,會調用initcall中的populate_rootfs() 函數來填充 rootfs。對于2,3的情況,是把initrd來填充rootfs,只不過,對2而言,原來的initrd和內核編在一起,在.init.ramfs段中,其中全局變量__initramfs_start和__initramfs_end分別指向這個數據段的起始地址和結束地址。如果.init.ramfs數據段大小不為0(initramfs_end - initramfs_start
!=
0),就說明這是initrd集成在內核數據段中。并且是cpio的initrd。而對于3,initrd是由bootloader加載到內存中的,這時
bootloader會把起始地址和結束地址傳遞給內核,內核中的全局initrd_start和initrd_end分別指向initrd的起始地址和
結束地址。對于4,則把 initrd 保存到 rootfs 的 /initrd.image
這個文件里。在后面,4會在prepare_namespace先掛載這個initrd,然后執(zhí)行里面的linuxrc,然后再掛載真實的文件系統。后面
的步驟2,3會在init_post()中調用/init,一般的發(fā)行版本的Linux中,initrd中的/init腳本會啟動udevd,加載必要的
設備驅動程序,然后掛載真正的根文件系統,最后再執(zhí)行真正的根文件系統上的initrd,這樣就這個啟動過程就順利的交接了。而對于4,則會調用根文件系
統上的/sbin/init(同1)。
所有的函數都在kernel_init中,從do_basic_setup()中的do_init_calls()到
prepare_namespace()(只有1,4要執(zhí)行此函數)最后到init_post()。(有關臨時根目錄的掛載并未在本文中包含,請參閱參考
文獻)總的來說,為了提高啟動速度,應該盡量避免使用initrd,而如果非要使用initrd,則應該使用cpio
initrd,因為ramdisk initrd不僅使用不方便,而且在內核中的處理過程也更加復雜,不推薦使用。
參考文獻:
1 Linux內核Ramdisk(initrd)機制
http://www./modules/article/view.article.php?9/c2#heading2
2 initrd 流程分析
http://hi.baidu.com/mczyh/blog/item/86153139527ed422b8998f17.html
3 解析linux根文件系統的掛載過程
http://bbs./viewthread.php?tid=306225
|