initrd的作用有三:
1.提高系統的可移植性
把更多的核心功能條目編譯成模組,不僅僅是為了減小核心體積,更重要的是面對各種不同的硬體架構,可以使用initrd中的linuxrc按需進行模組載入以驅動硬體,甚至對於cpu型別或者多處理機也可以進行手工選擇核心(配合syslinux這類boot loader)
2.livecd(光碟上的linux)必備的部件
現在的可啟動光碟都沿用2023年制定的el torito標準,它的啟動原理在於模擬軟盤啟動映像,這個映像的大小一般被限制在2800kb,也就是兩張軟盤的大小,它包含了syslinux(也可以用isolinux,它對映像的大小要求更寬鬆),syslinux的配置檔案,initrd.img以及核心。這時候核心的大小就必須要有約束了(當然,也有來自1mb實模式記憶體空間的約束),把更多的模組壓縮進initrd.img中去,可以縮小啟動映像的體積。
最重要的是,linuxrc指令碼對於硬碟,光碟機模組的載入至關重要,因為livecd要適應盡量多的硬體架構,所以它必須能按需載入模組,這時候 initrd就派上用場了。比如說,我們在vmware裡執行knoppix,knoppix的linuxrc就自動載入buslogic.o模組(通過輪換insmod來實現)。
3.在linuxrc指令碼中可以很方便地啟用個性化bootsplash
給出initrd的原理圖例(請參看附件)以及相關原始碼分析:
/*init/do_mounts.c中的prepare_namespace函式 -- 確定系統的根檔案系統*/void __init prepare_namespace(void)
is_floppy = major(root_dev) == floppy_major;
/*[2]嘗試處理initrd,見下*/
if (initrd_load())
goto out;
/*initrd_load()返回0,沒有處理initrd,存在以下兩種可能*/
/*或許已載入initrd但由於根裝置是ramdisk而沒有進行initrd處理,
則rd_doload==1,
呼叫rd_load_disk使用/dev/root取代上次rd_load_image中的/dev/root.old,root_dev=root_ram0*/
/*或許是沒有initrd以致,則rd_doload==0,root_dev!=root_ram0*/
/*rd_doload由arch/i386/kernel/setup.c中的setup_arch函式根據boot loader的命令列引數來決定*/
if (is_floppy && rd_doload && rd_load_disk(0))
root_dev = root_ram0;
/*根據root_dev掛載檔案系統*/
/*注意橙紅色標示的兩個mount_root()*/
mount_root();
/*無論有無經過initrd處理,最終為核心作最後chroot處理,確定系統的最終根檔案系統*/
out:
umount_devfs("/dev");
sys_mount(".", "/", null, ms_move, null);
sys_chroot(".");
security_sb_post_mountroot();
mount_devfs_fs ();
}
/*init/do_mounts_initrd.c*//*根據boot loader的命令列引數來判斷是否有initrd,如果沒有mount_initrd=0,否則為1*/
static int __initdata mount_initrd = 1;
static int __init no_initrd(char *str)
__setup("noinitrd", no_initrd);
...int __init initrd_load(void)
} sys_unlink("/initrd.image");
return 0;
}
/*init/do_mounts_initrd.c*/[/b]/*執行linuxrc(通常是指令碼,由靜態鏈結的sh來執行)*/
/*linuxrc指令碼的作用通常有以下這些:*/
/*載入所需模組(比如在虛擬機器中從livecd啟動就應該要載入scsi模組buslogic.o)*/
/*改變/proc/sys/kernel/real-root-dev來改變隨後的正常根檔案系統(見handle_initrd函式)*/
static int __init do_linuxrc(void * shell)
; extern char * envp_init;
sys_close(old_fd);sys_close(root_fd);
sys_close(0);sys_close(1);sys_close(2);
sys_setsid();
(void) sys_open("/dev/console",o_rdwr,0);
(void) sys_dup(0);
(void) sys_dup(0);
return execve(shell, argv, envp_init);
}/*[1]核心函式handle_initrd--負責initrd的處理*/
static void __init handle_initrd(void)
/* move initrd to rootfs' /old */
sys_fchdir(old_fd);
sys_mount("/", ".", null, ms_move, null);
/* switch root and cwd back to / of rootfs */
sys_fchdir(root_fd);
sys_chroot(".");
sys_close(old_fd);
sys_close(root_fd);
umount_devfs("/old/dev");
if (new_decode_dev(real_root_dev) == root_ram0)
root_dev = new_decode_dev(real_root_dev);
mount_root();
printk(kern_notice "trying to move old root to /initrd ... ");
error = sys_mount("/old", "/root/initrd", null, ms_move, null);
if (!error)
printk("okay\n");
else else
printk(!error ? "okay\n" : "failed\n");
}}
spring原始碼分析 spring原始碼分析
1.spring 執行原理 spring 啟動時讀取應用程式提供的 bean 配置資訊,並在 spring 容器中生成乙份相應的 bean 配置登錄檔,然後根據這張登錄檔例項化 bean,裝配好 bean 之間的依賴關係,為上 層應用提供準備就緒的執行環境。二 spring 原始碼分析 1.1spr...
思科VPP原始碼分析(dpo機制原始碼分析)
vpp的dpo機制跟路由緊密結合在一起。路由表查詢 ip4 lookup 的最後結果是乙個load balance t結構。該結構可以看做是乙個hash表,裡面包含了很多dpo,指向為下一步處理動作。每個dpo都是新增路由時的乙個path的結果。dpo標準型別有 dpo drop,dpo ip nu...
redux原始碼分析(三) 原始碼部分
下面是每個部分的一些解讀 createstore apicreatestore reducer,initialstate enhancer 曾經非常好奇這個函式的第二個引數到底是initialstate還是enhancer,因為見過兩種寫法都有的,以為是版本問題。看了原始碼才發現,都可以的。如果你不...