转:看看initramfs加载的完整流程


vim usr/initramfs_data.S
SECTIONS
{
      .init.ramfs : { *(.data) } // 包含所有data
}
.section .init.ramfs,"a"
.incbin "usr/initramfs_data.cpio.gz" //data为usr/initramfs_data.cpio.gz文件内容

vim arch/arm/kernel/vmlinux.lds.S
#ifdef CONFIG_BLK_DEV_INITRD
       . =ALIGN(32);
      __initramfs_start = .;
         usr/built-in.o(.init.ramfs)
      __initramfs_end = .;
#endif

vim init/initramfs.c
rootfs_initcall(populate_rootfs);
static int __init populate_rootfs(void)
{
    // 先unpackbuilt-in编译进内核的以__initramfs_start地址开始的fs数据
    char *err =unpack_to_rootfs(__initramfs_start,
          __initramfs_end - __initramfs_start,0);
    // 再unpackbootloader传过来的以initrd_start地址开始的fs数据
    err =unpack_to_rootfs((char *)initrd_start,
          initrd_end -initrd_start, 0);
}

生成initramfs.gz加载文件
scripts/gen_initramfs_list.sh -o /vobs/gliethttp/initramfs.gz/vobs/nfs/

如果-d后面不加任何参数那么将显示默认的initramfs中包含的文件
scripts/gen_initramfs_list.sh -d 

显示initramfs.cpio中的包含的文件
gunzip /vobs/gliethttp/initramfs.gz
cpio -i -t < /vobs/gliethttp/initramfs

或者直接显示initramfs.gz中包含的文件
gunzip -c /vobs/gliethttp/initramfs.gz | cpio -i -t

arch/arm/kernel/setup.c|730| paging_init(mdesc)
start_kernel
==> setup_arch(&command_line)
==> paging_init
==> bootmem_init
==> bootmem_reserve_initrd(node)会将phys_initrd_start后phys_initrd_size大小空间暂时保留,不被buddy回收管理[luther.gliethttp]
   然后initrd_start = __phys_to_virt(phys_initrd_start)存放虚拟地址

start_kernel
==> vfs_caches_init
==> mnt_init
==> init_rootfs
位于fs/ramfs/inode.c中,调用register_filesystem(&rootfs_fs_type);注册rootfs
接下来
init_mount_tree()函数将调用mnt = do_kern_mount("rootfs", 0, "rootfs",NULL);将rootfs挂在到/根目录下
然后使用如下两个函数,将后边建立线程的根目录指向rootfs,
set_fs_pwd(current->fs, ns->root,ns->root->mnt_root);
set_fs_root(current->fs, ns->root,ns->root->mnt_root);

init/do_mounts.c|153| __setup("root=", root_dev_setup);
比如cmdline传入参数"root=/dev/ram0" 
static int __init root_dev_setup(char *line)
{
   strlcpy(saved_root_name, line,sizeof(saved_root_name));
    return1;
}

__setup("root=", root_dev_setup);
在函数中将引用到saved_root_name

arch/arm/kernel/vmlinux.lds.S|46| *(.init.setup)
arch/x86/kernel/vmlinux_32.lds.S|131| *(.init.setup)
       __setup_start = .;
         *(.init.setup)
      __setup_end = .;

1. obsolete_checksetup
2. do_early_param

start_kernel
==> parse_args("Booting kernel", static_command_line,__start___param,
        __stop___param - __start___param,
        &unknown_bootoption);  //解析built-in的静态cmdline和静态param.
==> unknown_bootoption
==> obsolete_checksetup

arch/arm/kernel/vmlinux.lds
   __start___param = .;
    *(__param)//为kernel buit in的内容,我的kernel没有定义该存储区段
   __stop___param = .;


start_kernel
==> parse_early_param
==*>parse_early_options
==**> parse_args("early options", cmdline, NULL, 0,do_early_param) // 使用do_early_param函数解析参数
==> do_early_param 
2.6.30.4内核cmdline常用命令行参数与相应处理函数

static int __init do_early_param(char *param, char *val)
{
    structobs_kernel_param *p;

    for (p =__setup_start; p < __setup_end; p++) {
      if ((p->early && strcmp(param,p->str) == 0) ||
         (strcmp(param, "console") == 0 &&
          strcmp(p->str, "earlycon") == 0)
      ) {
         if (p->setup_func(val) != 0)
            printk(KERN_WARNING
                  "Malformed early option '%s'\n", param);
      }
    }
    
    return0;
}

static int __init parse_tag_initrd(const struct tag *tag)
{
   printk(KERN_WARNING "ATAG_INITRD is deprecated; "
       "pleaseupdate your bootloader.\n");
   phys_initrd_start = __virt_to_phys(tag->u.initrd.start); //如果传入正确值,那么kernel就启动不起来
   phys_initrd_size = tag->u.initrd.size;
    return0;
}

__tagtable(ATAG_INITRD, parse_tag_initrd);

start_kernel
==> rest_init
==> kernel_init
static int __init kernel_init(void * unused)
{
   lock_kernel();
   set_cpus_allowed_ptr(current,cpu_all_mask);
   init_pid_ns.child_reaper = current;

    cad_pid =task_pid(current);

   smp_prepare_cpus(setup_max_cpus);

   do_pre_smp_initcalls();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值