




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、一:前言 前段時(shí)間在編譯 kernel的時(shí)候發(fā)現(xiàn)rootfs掛載不上。相同的root選項(xiàng)設(shè)置舊版的image卻可 以。為了徹底解決這個(gè)問(wèn)題。研究了一下 rootfs的掛載過(guò)程。特總結(jié)如下,希望能給這部份 知識(shí)點(diǎn)比較迷茫的朋友一點(diǎn)幫助。二:roo一:前言 前段時(shí)間在編譯 kernel的時(shí)候發(fā)現(xiàn)rootfs掛載不上。相同的root選項(xiàng)設(shè)置舊版的image卻可 以。為了徹底解決這個(gè)問(wèn)題。研究了一下 rootfs的掛載過(guò)程。特總結(jié)如下,希望能給這部份 知識(shí)點(diǎn)比較迷茫的朋友一點(diǎn)幫助。二:rootfs的種類總的來(lái)說(shuō),rootfs分為兩種:虛擬 rootfs和真實(shí)rootfs.現(xiàn)在kernel的發(fā)展趨勢(shì)是將
2、更多的功 能放到用戶空間完成。以保持內(nèi)核的精簡(jiǎn)。虛擬 rootfs也是各linux發(fā)行廠商普遍采用的一 種方式??梢詫⒁徊糠莸某跏蓟ぷ鞣旁谔摂M的rootfs里完成。然后切換到真實(shí)的文件系統(tǒng).在虛擬rootfs的發(fā)展過(guò)程中。又有以下幾個(gè)版本:initramfs:Initramfs是在kernel 2.5中引入的技術(shù),實(shí)際上它的含義就是:在內(nèi)核鏡像中附加一個(gè)cpio包,這個(gè)cpio包中包含了一個(gè)小型的文件系統(tǒng),當(dāng)內(nèi)核啟動(dòng)時(shí),內(nèi)核將這個(gè) cpio包解開(kāi), 并且將其中包含的文件系統(tǒng)釋放到rootfs中,內(nèi)核中的一部分初始化代碼會(huì)放到這個(gè)文件系統(tǒng)中,作為用戶層進(jìn)程來(lái)執(zhí)行。這樣帶來(lái)的明顯的好處是精簡(jiǎn)了內(nèi)
3、核的初始化代碼,而且使得內(nèi)核的初始化過(guò)程更容易定制。這種這種方式的rootfs是包含在kernel image之中的.cpio-initrd: cpio 格式的 rootfsimage-initrd:傳統(tǒng)格式的 rootfs關(guān)于這兩種虛擬文件系統(tǒng)的制作請(qǐng)自行參閱其它資料三:rootfs文件系統(tǒng)的掛載過(guò)程 這里說(shuō)的rootfs不同于上面分析的rootfs。這里指的是系統(tǒng)初始化時(shí)的根結(jié)點(diǎn)。即/結(jié)點(diǎn)。它是其于內(nèi)存的rootfs文件系統(tǒng)。這部份之前在 << linux啟動(dòng)過(guò)程分析 >>和文件系統(tǒng)中已經(jīng)分 析過(guò)。為了知識(shí)的連貫性這里再重復(fù)一次。Start_kernel() mnt
4、_init(): void _init mnt_init(void)(init_rootfs();init_mount_tree();Init_rootfs的代碼如下: int _init init_rootfs(void)int err;err = bdi_init(&ramfs_backing_dev_info);if (err)return err;err = register_filesystem(&rootfs_fs_type);if (err)bdi_destroy(&ramfs_backing_dev_info);return err;這個(gè)函數(shù)很簡(jiǎn)單。就是
5、注冊(cè)了rootfs的文件系統(tǒng).init_mount_tree()代碼如下:static void _init init_mount_tree(void)(struct vfsmount *mnt;struct mnt_namespace *ns;struct path root;mnt = do_kern_mount("rootfs”, 0, "rootfs", NULL);if (IS_ERR(mnt)panic("Can't create rootfs");ns = kmalloc(sizeof(*ns), GFP_KERNEL);
6、if (!ns)panic("Can't allocate initial namespace");atomic_set(&ns->count, 1);INIT_LIST_HEAD(&ns->list);init_waitqueue_head(&ns->poll);ns->event = 0;list_add(&mnt->mnt_list, &ns->list);ns->root = mnt;mnt->mnt_ns = ns;init_task.nsproxy->mnt_n
7、s = ns;get_mnt_ns(ns);root.mnt = ns->root;root.dentry = ns->root->mnt_root;set_fs_pwd(current->fs, &root); set_fs_root(current->fs, &root);在這里,將rootfs文件系統(tǒng)掛載。它的掛載點(diǎn)默認(rèn)為”/”.最后切換進(jìn)程的根目錄和當(dāng)前目錄為” /”.這也就是根目錄的由來(lái)。不過(guò)這里只是初始化。等掛載完具體的文件系統(tǒng)之后,一般都會(huì)將根目錄切換到具體的文件系統(tǒng)。所以在系統(tǒng)啟動(dòng)之后,用mount命令是看不到rootfs的掛載信息
8、的.四:虛擬文件系統(tǒng)的掛載根目錄已經(jīng)掛上去了,可以掛載具體的文件系統(tǒng)了在 start_kernel()(Test_init() ckernel_init():static int _init kernel_init(void * unused)do_basic_setup();if (!ramdisk_execute_command)ramdisk_execute_command = "/init"if (sys_access(const char _user *) ramdisk_execute_command, 0) != 0) ramdisk_execute_comm
9、and = NULL;prepare_namespace();/* Ok, we have completed the initial bootup, and* we're essentially up and running. Get rid of the* initmem segments and start the user-mode stuff.*/init_post();return 0;do_basic_setup()是一個(gè)很關(guān)鍵的函數(shù),所有直接編譯在 kernel中的模塊都是由它啟動(dòng)的。代碼片段如下:static void _init do_basic_setup(voi
10、d)/* drivers will send hotplug events */ init_workqueues();usermodehelper_init();driver_init();init_irq_proc();do_initcalls();Do_initcalls()用來(lái)啟動(dòng)所有在 _initcall_start和_initcall_end段的函數(shù),而靜態(tài)編譯進(jìn)內(nèi)核的 modules也會(huì)將其入口放置在這段區(qū)間里。跟根文件系統(tǒng)相關(guān)的初始化函數(shù)都會(huì)由rootfs_initcall ()所引用。注意到有以下初始化函數(shù):rootfs_initcall(populate_rootfs);也就
11、是說(shuō)會(huì)在系統(tǒng)初始化的時(shí)候會(huì)調(diào)用populate_rootfs進(jìn)行初始化。代碼如下:static int _init populate_rootfs(void)char *err = unpack_to_rootfs(_initramfs_start,_initramfs_end - _initramfs_start, 0);if (err)panic(err);if (initrd_start) #ifdef CONFIG_BLK_DEV_RAMint fd;printk(KERN_INFO "checking if image is initramfs.");err =
12、unpack_to_rootfs(char *)initrd_start,initrd_end - initrd_start, 1);if (!err) printk(" it isn");unpack_to_rootfs(char *)initrd_start,initrd_end - initrd_start, 0); free_initrd();return 0;printk("it isn't (%s); looks like an initrdn", err);fd = sys_open("/initrd.image”, O_
13、WRONL Y|O_CREA T, 0700);if (fd >= 0) sys_write(fd, (char *)initrd_start,initrd_end - initrd_start); sys_close(fd);free_initrd();#elseprintk(KERN_INFO "Unp acking initramfs.");err = unpack_to_rootfs(char *)initrd_start,initrd_end - initrd_start, 0);if (err)panic(err);printk(" donen&
14、quot;);free_initrd();#endifreturn 0;unpack_to_rootfs :顧名思義就是解壓包,并將其釋放至rootfs。它實(shí)際上有兩個(gè)功能,一個(gè)是釋放包,一個(gè)是查看包,看其是否屬于cpio結(jié)構(gòu)的包。功能選擇是根據(jù)最后的一個(gè)參數(shù)來(lái)區(qū)分的.在這個(gè)函數(shù)里,對(duì)應(yīng)我們之前分析的三種虛擬根文件系統(tǒng)的情況。一種是跟kernel融為一體的initramfs.在編譯 kernel的 時(shí)候,通過(guò) 鏈接腳 本將其 存放在_initramfs_start 至 _initramfs_end的區(qū)域。這種情況下,直接調(diào)用unpack_to_rootfs將其釋放到根目錄.如果不是屬于這種形式
15、的。 也就是_initramfs_start和_initramfs_end的值相等,長(zhǎng)度為零。 不會(huì)做 任何處理。退出.對(duì)應(yīng)后兩種情況。 從代碼中看至叭 必須要配制 CONFIG_BLK_DEV_RAM 才會(huì)支持 image-initrd。否則全當(dāng)成 cpio-initrd的形式處理。對(duì)于是cpio-initrd的情況。直接將其釋放到根目錄。對(duì)于是 image-initrd的情況。將其釋放 到/initrd.image.最后將initrd內(nèi)存區(qū)域歸入伙伴系統(tǒng)。這段內(nèi)存就可以由操作系統(tǒng)來(lái)做其它 的用途了。接下來(lái),內(nèi)核對(duì)這幾種情況又是怎么處理的呢?不要著急。往下看:回到kernel_init()這
16、個(gè)函數(shù):static int _init kernel_init(void * unused)do_basic_setup();/* check if there is an early userspace init. If yes, let it do all* the work*/ramdisk_execute_command = "/init"if (sys_access(const char _user *) ramdisk_execute_command, 0) != 0) ramdisk_execute_command = NULL;prepare_namesp
17、ace();/* Ok, we have completed the initial bootup, and* we're essentially up and running. Get rid of the* initmem segments and start the user-mode stuff.*/init_post();return 0;ramdisk_execute_command:在kernel解析引導(dǎo)參數(shù)的時(shí)候使用。如果用戶指定了 init文件路徑,即使用了 init= ",就會(huì)將這個(gè)參數(shù)值存放到這里。如果沒(méi)有指定init文件路徑。默認(rèn)為/init對(duì)應(yīng)于前面
18、一段的分析,我們知道,對(duì)于 initramdisk和cpio-initrd的情況,都會(huì)將虛擬根文 件系統(tǒng)釋放到根目錄。如果這些虛擬文件系統(tǒng)里有/init這個(gè)文件。就會(huì)轉(zhuǎn)入到 init_post()。Init_post()代碼如下:static int noinline init_post(void)free_initmem();unlock_kernel();mark_rodata_ro();system_state = SYSTEM_RUNNING;numa_default_policy();if (sys_open(const char _user *) "/dev/consol
19、e", O_RDWR, 0) < 0)printk(KERN_W ARNING "Warning: unable to open an initial console.n");(void) sys_dup(0);(void) sys_dup(0);if (ramdisk_execute_command) (run_init_process(ramdisk_execute_command);printk(KERN_W ARNING "Failed to execute %sn",ramdisk_execute_command);/* We
20、try each of these until one succeeds.* The Bourne shell can be used instead of init if we are* trying to recover a really broken machine.*/if (execute_command) (run_init_process(execute_command);printk(KERN_W ARNING "Failed to execute %s. Attempting ""defaults.n”, execute_command);run
21、_init_process("/sbin/init");run_init_process("/etc/init");run_init_process("/bin/init");run_init_process("/bin/sh");panic("No init found. Try passing init= option to kernel.");從代碼中可以看中,會(huì)依次執(zhí)行指定的init文件,如果失敗,就會(huì)執(zhí)行/sbin/init, /etc/init,/bin/init,/bin/sh注意
22、的是,run_init_process在調(diào)用相應(yīng)程序運(yùn)行的時(shí)候,用的是kernel_execve。也就是說(shuō)調(diào)用進(jìn)程會(huì)替換當(dāng)前進(jìn)程。 只要上述任意一個(gè)文件調(diào)用成功,就不會(huì)返回到這個(gè)函數(shù)。 如果上面幾個(gè)文件都無(wú)法執(zhí)行。打印出沒(méi)有找到init文件的錯(cuò)誤。對(duì)于image-hdr或者是虛擬文件系統(tǒng)中沒(méi)有包含/init的情況,會(huì)由prepare_namespace(處理。代碼如下:void _init prepare_namespace(void)(int is_floppy;if (root_delay) (printk(KERN_INFO "Waiting %dsec before moun
23、ting root device.n", root_delay);ssleep(root_delay);/* wait for the known devices to complete their probing */while (driver_probe_done() != 0) msleep(100);/mtd的處理md_run_setup();if (saved_root_name0) root_device_name = saved_root_name;if (!strncmp(root_device_name, "mtd", 3) mount_bloc
24、k_root(root_device_name, root_mountflags);goto out;ROOT_DEV = name_to_dev_t(root_device_name);if (strncmp(root_device_name, "/dev/", 5) = 0)root_device_name += 5;if (initrd_load() goto out;/* wait for any asynchronous scanning to complete */if (ROOT_DEV = 0) && root_wait) printk(KE
25、RN_INFO "Waiting for root device %s.n”,saved_root_name);while (driver_probe_done() != 0 |(ROOT_DEV = name_to_dev_t(saved_root_name) = 0) msleep(100);is_floppy = MAJOR(ROOT_DEV) = FLOPPY_MAJOR;if (is_floppy && rd_doload && rd_load_disk(0) ROOT_DEV = Root_RAM0;mount_root();out:sys
26、_mount(".”, ”/”, NULL, MS_MOVE, NULL);sys_chroot(".”);這里有幾個(gè)比較有意思的處理,首先用戶可以用root=來(lái)指定根文件系統(tǒng)。它的值保存在saved_root_name中。如果用戶指定了以 mtd開(kāi)始的字串做為它的根文件系統(tǒng)。就會(huì)直接去 掛載。這個(gè)文件是 mtdblock的設(shè)備文件。否則將設(shè)備結(jié)點(diǎn)文件轉(zhuǎn)換為ROOT_DEV即設(shè)備節(jié)點(diǎn)號(hào)然后,轉(zhuǎn)向initrd_load()執(zhí)行initrd預(yù)處理后,再將具體的根文件系統(tǒng)掛載。注意到,在這個(gè)函數(shù)末尾。會(huì)調(diào)用sys_mount()來(lái)移動(dòng)當(dāng)前文件系統(tǒng)掛載點(diǎn)到”/”目錄下。然后將根目錄
27、切換到當(dāng)前目錄。這樣,根文件系統(tǒng)的掛載點(diǎn)就成為了我們?cè)谟脩艨臻g所看到的” /” 了 .對(duì)于其它根文件系統(tǒng)的情況,會(huì)先經(jīng)過(guò)initrd的處理。即int _init initrd_load(void)(if (mount_initrd) (create_dev("/dev/ram", Root_RAM0);/* Load the initrd data into /dev/ram0. Execute it as initrd* unless /dev/ram0 is supposed to be our actual root device,* in that case the
28、 ram disk is just set up here, and gets* mounted in the normal path.*/if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) (sys_unlink("/initrd.image");handle_initrd();return 1;sys_unlink("/initrd.image");return 0;建立一個(gè) ROOT_RAM)的設(shè)備節(jié)點(diǎn),并將 /initrd/.image 釋放
29、到這個(gè)節(jié)點(diǎn)中,/initrd.image 的 內(nèi)容,就是我們之前分析的image-initrd。如果根文件設(shè)備號(hào)不是ROOT_RAM0(用戶指定的根文件系統(tǒng)不是/dev/ram0就會(huì)轉(zhuǎn)入到handle_initrd()如果當(dāng)前根文件系統(tǒng)是/dev/ram0.將其直接掛載就好了。handle_initrd ()代碼如下:static void _init handle_initrd(void)int error;int pid;real_root_dev = new_encode_dev(ROOT_DEV);create_dev("/dev/root.old”, Root_RAM0);
30、/* mount initrd on rootfs' /root */mount_block_root("/dev/root.old", root_mountflags & MS_RDONL Y);sys_mkdir("/old", 0700);root_fd = sys_open("/", 0, 0);old_fd = sys_open("/old", 0, 0);/* move initrd over / and chdir/chroot in initrd root */sys_chdir(&
31、quot;/root");sys_mount(".", "/", NULL, MS_MOVE, NULL);sys_chroot(".”);/* In case that a resume from disk is carried out by linuxrc or one of* its children, we need to tell the freezer not to wait for us.*/current->flags |= PF_FREEZER_SKIP;pid = kernel_thread(do_linux
32、rc, "/linuxrc", SIGCHLD);if (pid > 0)while (pid != sys_wait4(-1, NULL, 0, NULL)yield();current->flags &= PF_FREEZER_SKIP;/* 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(".”);sy
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030中國(guó)益生菌補(bǔ)充品市場(chǎng)供應(yīng)渠道與未來(lái)銷售渠道研究報(bào)告
- 2025至2030中國(guó)電子相冊(cè)軟件行業(yè)市場(chǎng)發(fā)展趨勢(shì)及有效策略與實(shí)施路徑評(píng)估報(bào)告
- 2025至2030中國(guó)電動(dòng)牙鉆機(jī)行業(yè)深度研究及發(fā)展前景投資評(píng)估分析
- 2025至2030中國(guó)珩磨油行業(yè)深度研究及發(fā)展前景投資評(píng)估分析
- 2025至2030中國(guó)特殊需要的嬰兒車行業(yè)發(fā)展趨勢(shì)分析與未來(lái)投資戰(zhàn)略咨詢研究報(bào)告
- 教育心理學(xué)學(xué)生情感教育的核心
- 遼寧省沈文新高考研究聯(lián)盟2024-2025學(xué)年高一下學(xué)期7月期末質(zhì)量監(jiān)測(cè)地理試卷(含答案)
- 華邦健康知識(shí)培訓(xùn)
- 商業(yè)培訓(xùn)中如何利用教育大數(shù)據(jù)提升教學(xué)效果
- 教育心理學(xué)與學(xué)習(xí)環(huán)境優(yōu)化
- 哇哈哈品牌管理制度
- 2025年第十屆“學(xué)憲法、講憲法”網(wǎng)絡(luò)知識(shí)競(jìng)賽題庫(kù)(含答案)
- 北師大版四年級(jí)下冊(cè)數(shù)學(xué)計(jì)算題每日一練帶答案(共30天)
- HIV實(shí)驗(yàn)室風(fēng)險(xiǎn)評(píng)估-
- 最新四川水利工程質(zhì)量備案表格填寫(xiě)范例
- 臨海市括蒼鎮(zhèn)鎮(zhèn)區(qū)控制性詳細(xì)規(guī)劃
- 《云南省建筑工程資料管理規(guī)程應(yīng)用指南)(上下冊(cè))
- 工程更改控制程序DFCPQEOMS-06
- XX集團(tuán)債權(quán)清收工作管理辦法
- 送電線路工程跨越河流架線施工專項(xiàng)方案
- 臺(tái)州市幼兒園教師考核表.
評(píng)論
0/150
提交評(píng)論