real_root_dev = new_encode_dev(ROOT_DEV); // real_root_dev全局变量保存的是存放realfs的设备的设备号 create_dev("/dev/root.old", Root_RAM0); // 建立一个Root_RAM0类型的/dev/root.old设备节点,实际上就是一ramdisk // 访问root.old和上层函数中创建的ram节点是一样的,对应的是同一设备,内容一样 /* mount initrd on rootfs's /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); // 将/dev/root.old中的initrd文件系统挂载到了rootfs的/root目录下 sys_mkdir("/old", 0700); /* 在rootfs的根目录下创建old目录 */ root_fd = sys_open("/", 0, 0); // 通过这种方式保存原根目录的描述符 old_fd = sys_open("/old", 0, 0); // 通过这种方式保存/old的描述符 /* move initrd over / and chdir/chroot in initrd root */ sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); // 进入/root目录,将当前目录mount为根目录,然后切换当前目录为程序执行所 // 参考的根目录位置 /* * 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); // 启动一进程执行/linuxrc,并等待其执行完。可以看出前面执行sys_chroot(".")的意义 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); // 进入old_fd描述的目录,再将现在的根目录mount到原来根目录下的old目录中 /* 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) { sys_chdir("/old"); return; } // 取真实文件系统所在设备的设备号 ROOT_DEV = new_decode_dev(real_root_dev); mount_root(); // 将真实文件系统挂载到/root目录中 // 注意mount_root()实际调用了函数mount_block_root()函数来实现mount,之后会 // chdir(/root),否则后面返回上上层函数有个地方可能看不明白 printk(KERN_NOTICE "Trying to move old root to /initrd ... "); error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); // 将/old移植/root/initrd中去 if (!error) printk("okay/n"); else { int fd = sys_open("/dev/root.old", O_RDWR, 0); if (error == -ENOENT) printk("/initrd does not exist. Ignored./n"); else printk("failed/n"); printk(KERN_NOTICE "Unmounting old root/n"); sys_umount("/old", MNT_DETACH); // 移动不成功就将/old目录卸载掉 printk(KERN_NOTICE "Trying to free ramdisk memory ... "); if (fd < 0) { error = fd; } else { error = sys_ioctl(fd, BLKFLSBUF, 0); sys_close(fd); } printk(!error ? "okay/n" : "failed/n"); } } +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 至此,通过image-initrd将真实的文件系统挂载起来了