static struct file_system_type rootfs_fs_type = { .name = "rootfs", .get_sb = rootfs_get_sb, //get_sb的方法为rootfs_get_sb,这个在init_mnt_tree中会用到 .kill_sb = kill_litter_super, }; |
initrd 的英文含义是 boot loader initialized RAM disk,就是由 boot loader 初始化的内存盘。在 linux内核启动前, boot loader 会将存储介质中的 initrd 文件加载到内存,内核启动时会在访问真正的根文件系统前先访问该内存中的 initrd中的脚本文件。在 boot loader 配置了 initrd 的情况下,内核启动被分成了两个阶段,第一阶段先执行 initrd 文件系统中的linuxrc,完成加载驱动模块等任务,第二阶段才会执行真正的根文件系统中的 /sbin/init 进程。这样做的好处是,linux的一些功能,例如对硬件的支持可以做成可加载模块,而不是直接编译到内核,通过修改配置文件,就可以在启动的时候,根据需要加载某些模块,这样就避免了linux的冗余。 initrd中的内容并不是直接拷贝的内存直接访问的,而是借助ramdisk,在initrd文件加载到内存中,然后判断是initrd格式后,在rootfs的”/”下为其建立一个initrd.image文件,接着注册一个ramdisk设备(/dev/ram0),将initrd.image文件中的内容拷贝到这个内存闪盘中,并将这个设备作为原始根文件系统,这样就可以访问initrd中的文件实现模块的加载和根文件系统的安装了,根文件系统安装后会替换调原始文件系统,用真正的文件系统中的”\”替换调rootfs的”\”。 即: image-initrd的处理流程 1. boot loader把内核以及initrd文件加载到内存的特定位置。 2. 内核判断initrd的文件格式,如果不是cpio格式,将其作为image-initrd处理。 3. 内核将initrd的内容保存在rootfs下的/initrd.image文件中。 4. 内核将/initrd.image的内容读入/dev/ram0设备中,也就是读入了一个内存盘中。 5. 接着内核以可读写的方式把/dev/ram0设备挂载为原始的根文件系统。 6. .如果/dev/ram0被指定为真正的根文件系统,那么内核跳至最后一步正常启动。 7. 执行initrd上的/linuxrc文件,linuxrc通常是一个脚本文件,负责加载内核访问根文件系统必须的驱动, 以及加载根文件系统。 8. /linuxrc执行完毕,常规根文件系统被挂载 9. 如果常规根文件系统存在/initrd目录,那么/dev/ram0将从/移动到/initrd。否则如果/initrd目录不存在, /dev/ram0将被卸载。 10. 在常规根文件系统上进行正常启动过程 ,执行/sbin/init。 |
砭石祛斑泥 static int init(void * unused){ [1] populate_rootfs(); [2] if (sys_access((const char __user *) "/init", 0) == 0) execute_command = "/init"; else prepare_namespace(); [3] if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING "Warning: unable to open an initial console.\n"); (void) sys_dup(0); (void) sys_dup(0); [4] if (execute_command) run_init_process(execute_command); run_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."); } |
……….. switchroot --movedev /sysroot |
void __init populate_rootfs(void){ [1] char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start, 0); [2] if (initrd_start) { [3] err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start, 1); [4] if (!err) { printk(" it is\n"); unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start, 0); free_initrd_mem(initrd_start, initrd_end); return; } [5] fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 700); if (fd >= 0) { sys_write(fd, (char *)initrd_start, initrd_end - initrd_start); sys_close(fd); free_initrd_mem(initrd_start, initrd_end); } } |
void __init prepare_namespace(void){ [1] if (initrd_load()) goto out; out: umount_devfs("/dev"); [2] sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); security_sb_post_mountroot(); mount_devfs_fs (); } |
int __init initrd_load(void) { [1] if (mount_initrd) { 透射电镜制样 create_dev("/dev/ram", Root_RAM0, NULL); [2] if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) { sys_unlink("/initrd.image"); handle_initrd(); return 1; } } sys_unlink("/initrd.image"); return 0; } |
static void __init handle_initrd(void){ [1] real_root_dev = new_encode_dev(ROOT_DEV); [2] create_dev("/dev/root.old", Root_RAM0, NULL); mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); [3] 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 */ [4] sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); mount_devfs_fs (); [5] pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); if (pid > 0) { while (pid != sys_wait4(-1, &i, 0, NULL)) yield(); 热流道温控器 } /* move initrd to rootfs' /old */ sys_fchdir(old_fd); sys_mount("/", ".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ [6] sys_fchdir(root_fd); 最大功率点跟踪 sys_chroot("."); sys_close(old_fd); sys_close(root_fd); umount_devfs("/old/dev"); [7] if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir("/old"); return; } [8] ROOT_DEV = new_decode_dev(real_root_dev); mount_root(); [9] 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 { int fd = sys_open("/dev/root.old", O_RDWR, 0); printk("failed\n");城市排水 printk(KERN_NOTICE "Unmounting old root\n"); sys_umount("/old", MNT_DETACH); 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"); } |
本文发布于:2024-09-25 19:24:02,感谢您对本站的认可!
本文链接:https://www.17tex.com/tex/2/104182.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |