linux根文件系统的挂载过程详解 linux文件挂载是什么意思( 三 )


}
从代码中可以看中,会依次执行指定的init文件,如果失败 , 就会执行/sbin/init, /etc/init,, /bin/init,/bin/sh
注意的是,run_init_process在调用相应程序运行的时候,用的是kernel_execve 。也就是说调用进程会替换当前进程 。只要上述任意一个文件调用成功,就不会返回到这个函数 。如果上面几个文件都无法执行 。打印出没有找到init文件的错误 。
对于image-hdr或者是虚拟文件系统中没有包含 /init的情况,会由prepare_namespace()处理 。代码如下:
void __init prepare_namespace(void)
{
int is_floppy;
if (root_delay) {
printk(KERN_INFO "Waiting %dsec before mounting root device...n",
root_delay);
ssleep(root_delay);
}
/* wait for the known devices to complete their probing */
while (driver_probe_done() != 0)
msleep(100);
http://mtd的处理
md_run_setup();
if (saved_root_name[0]) {
root_device_name = saved_root_name;
if (!strncmp(root_device_name, "mtd", 3)) {
mount_block_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(KERN_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_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot(".");
}
这里有几个比较有意思的处理,首先用户可以用root=来指定根文件系统 。它的值保存在saved_root_name中 。如果用户指定了以mtd开始的字串做为它的根文件系统 。就会直接去挂载 。这个文件是mtdblock的设备文件 。
否则将设备结点文件转换为ROOT_DEV即设备节点号
然后,转向initrd_load()执行initrd预处理后,再将具体的根文件系统挂载 。
注意到,在这个函数末尾 。会调用sys_mount()来移动当前文件系统挂载点到”/”目录下 。然后将根目录切换到当前目录 。这样,根文件系统的挂载点就成为了我们在用户空间所看到的”/”了.
对于其它根文件系统的情况,会先经过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 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;
}
建立一个ROOT_RAM)的设备节点,并将/initrd/.image释放到这个节点中,/initrd.image的内容,就是我们之前分析的image-initrd 。
如果根文件设备号不是ROOT_RAM0( 用户指定的根文件系统不是/dev/ram0就会转入到handle_initrd()
如果当前根文件系统是/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);
/* mount initrd on rootfs' /root */
mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
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("/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_linuxrc, "/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(".");
sys_close(old_fd);
sys_close(root_fd);
if (new_decode_dev(real_root_dev) == Root_RAM0) {

推荐阅读