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