歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux啟動原理之-initrd和Debian實例

Linux啟動原理之-initrd和Debian實例

日期:2017/2/28 16:20:06   编辑:Linux教程

init/main.c中的start_kernel函數完成了所有的全局特性初始化,這些全局特性包括內核運轉所需要的基礎設施,比如虛擬內存設施,進程調度設施,中斷設施,緩存設施,VFS設施等,接下來啟動1號進程的內核部分,在start_kernel的最後rest_init函數中啟動之:
static void noinline rest_init(void)
{
kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
numa_default_policy();
unlock_kernel();
cpu_idle();
}
因此init/main.c中的init內核線程函數即是1號進程的內核部分,它完成內核的另一部分初始化之後即exec到1號進程的用戶態,從此一直到關機或者重啟,不再返回內核態,實際上exec本質上替換了進程地址空間,也就無從返回了。
init函數主要進行另一部分的初始化,涉及驅動,網絡協議棧,以及為1號進程用戶態即init進程准備環境,其中最為重要的就是populate_rootfs函數,在啟動initrd的情況下,最為重要的是它將initrd的內存寫到了一個文件當中或者直接將initrd的內容寫到整個rootfs:
1.將內容寫到文件:
fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 700);
if (fd >= 0) {
sys_write(fd, (char *)initrd_start, initrd_end - initrd_start); //將initrd的內容寫入文件
sys_close(fd);
free_initrd_mem(initrd_start, initrd_end); //釋放initrd原始內容所占用的內存
}
2.將內容直接放到rootfs:根據rootfs和initrd的內存地址信息直接寫。
可見sys_open調用創建了一個文件,即/initrd.image,它的內容就是initrd內存盤的內容,可是它在/下被創建,在linux中,所有的文件都要有一個“文件系統”作為載體,這個/目錄所在的文件系統是什麼呢?其實是一個內存盤,在start_kernel中的vfs_caches_init負責初始化文件系統,也就是VFS,這是一個虛擬文件系統的框架,其實現如下:
void __init vfs_caches_init(unsigned long mempages)
{
unsigned long reserve;

/* Base hash sizes on available memory, with a reserve equal to
150% of current kernel size */

reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
mempages -= reserve;

names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, filp_ctor, filp_dtor);
dcache_init(mempages);
inode_init(mempages);
files_init(mempages);
mnt_init(mempages);
bdev_cache_init();
chrdev_init();
}
在mnt_init中初始化了一個rootfs:
int __init init_rootfs(void)
{
return register_filesystem(&rootfs_fs_type);
}
然後在init_mount_tree中調用do_kern_mount掛載了這個rootfs作為“根”,接下來在init函數中創建/initrd.image就有所依托了,它就是在rootfs中創建了一個文件:/initrd.image,rootfs本質上是一個內存文件系統,因為此時還沒有加載任何驅動,更別說磁盤,磁帶,網卡驅動了,因此文件系統也只能是內存式的。linux的vfs功能十分強大,以文件作為接口使初始化過程如此簡潔!
接下來就要加載驅動了,do_basic_setup初始化了所有硬編譯進內核的驅動,然而驅動並不一定要編譯進內核,而這些驅動可能對於加載基於磁盤的根文件系統還至關重要,比如ide驅動,比如scsi驅動等,這些就由initrd來加載了,initrd的本質是一只雞,也就是在有磁盤根文件系統這個“蛋”之前先要有一只“雞”。
接下來prepare_namespace登場,我們可以看到在populate_rootfs結束後分開了兩條線索:
if (sys_access((const char __user *) "/init", 0) == 0)
execute_command = "/init";
else
prepare_namespace();

Copyright © Linux教程網 All Rights Reserved