Chinaunix

标题: initrd与initramfs比较 [打印本页]

作者: asuka2001    时间: 2013-06-01 11:35
标题: initrd与initramfs比较
本帖最后由 asuka2001 于 2013-06-01 11:42 编辑



绿色代表initramfs依赖项不满足则为空函数,红色代表initrd依赖项不满足则为空函数

相关代码位于 init/

                             initramfs                                                    initrd

依赖项                BLK_DEV_INITRD                        BLK_DEV_INITRD && BLK_DEV_RAM

源文件                initramfs.c                                        initramfs.c
                        do_mounts_initrd.c                        do_mounts_initrd.c
                                                                        do_mounts_rd.c


initramfs:
        __initramfs_start定义于 include/asm-generic/vmlinux.lds.h
        __initramfs_size定义于 usr/initramfs_data.S


initrd: initrd_start, initrd_end

        1. x86体系中: reserve_initrd() [arch/x86/kernel/setup.c]中

                initrd_start = boot_params.hdr.ramdisk_image (initrd的起始物理地址) + PAGE_OFFSET (固定映射偏移, 如0xC0000000)
                initrd_end = initrd_start + boot_param.hdr.ramdisk_size

                这样 initrd_start, initrd_end均成为内核的虚拟地址,可以直接访问
                struct boot_params和 struct setup_header, 为x86中 bootloader向 kernel传参方式,详见 [arch/x86/include/asm/bootparam.h]与 Documentation/x86/boot.txt

        2. arm体系中:
                1). parse_tag_initrd2() [arch/arm/mm/init.c]中
                        phys_initrd_start = tag->u.initrd.start (initrd的起始物理地址)
                        phys_initrd_size = tag->u.initrd.size

                2). arm_memblock_init() [arch/arm/mm/init.c]中
                        initrd_start = __phys_to_virt(phys_initrd_start)
                        initrd_end = initrd_start + phys_initrd_size

                3). struct tag [arch/arm/include/asm/setup.h], 为 ARM中 bootloader向 kernel传参方式,详见 Documentation/arm/booting


populate_rootfs()

        1. unpack_to_rootfs()只能正确识别 initramfs类型的压缩 rootfs (cpio镜像)

        2. 解压内核中附带的 cpio镜像: unpack_to_rootfs(__initramfs_start, __initramfs_size)

        3. bootloader装载了内存镜像给内核:

                1). 装载的是 initramfs,合并到 rootfs

                2). 装载的是 initrd, 将 initrd的内容读入到 /initrd.image

                3). 调用 free_initrd(),释放 initrd所占用内存

        4. 如果 populate_rootfs()成功加载了 initramfs,则 sys_access(ramdisk_execute_command, 0)应该成功,直接跳过 prepare_namespace()执行


initrd_load()

        1. 创建 /dev/ram, 设备节点号为 Root_RAM0

        2. 调用 rd_load_image()将/initrd.image写入到 /dev/ram

        3. 若/dev/ram不是最后的 rootfs,则调用 handle_initrd(); 否则 ROOT_DEV == Root_RAM0, initrd_load()返回0


handle_initrd()

        /* 将进入 handle_initrd()时的根目录命名为 r0, == 代表两者相等或直接映射关系, ===> 代表路径查询最终会导向该目标 */

        01. 创建设备节点 /dev/root.old, 设备节点号为 Root_RAM0, 故其与 /dev/ram为同一设备

        02. 将 initrd挂载为 /root, 即 r0/root == initrd

        03. root_fd == r0, old_fd == r0/old

        04. sys_chdir("/root"): CWD == r0/root

        05. sys_mount(".", "/", NULL, MS_MOVE, NULL): / ===> r0/root,此时 current->fs->root.dentry != r0/root的 dentry,但路径查询时将跳转到 r0/root的 dentry上

        06. sys_chroot("."): / == r0/root

        07. kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD): /linuxrc == r0/root/linuxrc

        08. sys_fchdir(old_fd): CWD == r0/old

        09. sys_mount("/", ".", NULL, MS_MOVE, NULL): CWD (r0/old) ===> r0/root(即 initrd)

        10. sys_fchdir(root_fd): CWD == r0

        11. sys_chroot("."): / == r0

        12. ROOT_DEV = new_decode_dev(real_root_dev),获取到 rootfs实际所在设备的设备节点号

        13. 调用 mount_root():
                1). create_dev("/dev/root", ROOT_DEV): /dev/root == r0/dev/root

                2). mount_block_root("/dev/root", root_mountflags)搜索合适的文件系统,继续调用 do_mount_root():

                        a). sys_mount(name, "/root", fs, flags, data): 将 r0/dev/root挂载到了 /root,即 r0/root下为真正的 rootfs

                        b). sys_chdir("/root"): CWD == r0/root

        14. sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL): /root/initrd ===> r0/old (即initrd)

        15. 返回 initrd_load(),最终将返回 prepare_namespace():
                1). initrd_load()返回1, 跳转到 out: 处执行

                2). sys_mount(".", "/", NULL, MS_MOVE, NULL): / ===> r0/root

                3). sys_chroot("."): / == r0/root,则此时 /initrd ===> r0/old (即initrd)


作者: asuka2001    时间: 2013-06-01 11:39
没有贴源代码,基于 linux 3.6.2




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2