- 论坛徽章:
- 17
|
本帖最后由 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)
|
|