免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2585 | 回复: 1

[其他] initrd与initramfs比较 [复制链接]

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
发表于 2013-06-01 11:35 |显示全部楼层
本帖最后由 asuka2001 于 2013-06-01 11:42 编辑

initramfs initrd.jpeg

绿色代表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)

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
发表于 2013-06-01 11:39 |显示全部楼层
没有贴源代码,基于 linux 3.6.2
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP