start_kernel之挂载根文件系统

start_kernel之挂载根文件系统

head.s最终会调用start_kernel函数
执行start_kernel的目的:挂载根文件系统,启动应用APP环境

asmlinkage void __init start_kernel(void)
    printk(KERN_NOTICE "%s", linux_banner);
    setup_arch(&command_line);//获取cmdline,初始化硬件
    setup_command_line(command_line);
    printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
    console_init();//初始化console
    rest_init();

static noinline void __init_refok rest_init(void)
    kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);//启动一个内核线程为kernel_init
    schedule();

static int __init kernel_init(void * unused)
    prepare_namespace();
        mount_root();//挂载根文件系统
    init_post();//运行应用程序
        run_init_process("/sbin/init");
        run_init_process("/etc/init");
        run_init_process("/bin/init");
        run_init_process("/bin/sh");

举例内核怎么知道挂载那个根文件系统
假设在启动的时候传入参数:

bootargs=noinitrd root=/dev/mtdblock3 rootfstype=yaffs2 init=/init console=ttySAC0
bootcmd=nand read.jffs2 0xc0008000 kernel;bootm 0xc0008000
void __init prepare_namespace(void)
    if (saved_root_name[0]) {
        root_device_name = saved_root_name;
        if (!strncmp(root_device_name, "mtd", 3) ||
            !strncmp(root_device_name, "ubi", 3)) {
            mount_block_root(root_device_name, root_mountflags);
            goto out;
        }
        ROOT_DEV = name_to_dev_t(root_device_name);
        if (strncmp(root_device_name, "/dev/", 5) == 0)
            root_device_name += 5;
    }
//搜索一下saved_root_name
static int __init root_dev_setup(char *line)
{
    strlcpy(saved_root_name, line, sizeof(saved_root_name));
    return 1;
}
__setup("root=", root_dev_setup);
//分析__setup()
#define __setup(str, fn) __setup_param(str, fn, fn, 0)
#define __setup_param(str, unique_id, fn, early)            \
    static const char __setup_str_##unique_id[] __initconst \
        __aligned(1) = str; \
    static struct obs_kernel_param __setup_##unique_id  \
        __used __section(.init.setup)           \
        __attribute__((aligned((sizeof(long)))))    \
        = { __setup_str_##unique_id, fn, early }
//我们将其展开:
__setup("root=", root_dev_setup);
__setup_param("root=", root_dev_setup, root_dev_setup, 0)

static const char __setup_str_root_dev_setup[] __initconst  \  //字符串
        __aligned(1) = "root="; \
static struct obs_kernel_param __setup_root_dev_setup \
__used __section(.init.setup) __attribute__((aligned((sizeof(long))))) \\结构体
={
        __setup_str_root_dev_setup,//名字
        root_dev_setup,//函数
        0
    }

struct obs_kernel_param {
    const char *str;
    int (*setup_func)(char *);
    int early;
};
//struct obs_kernel_param __setup_root_dev_setup 这个结构体什么时候被使用
//在内核中搜索.init.setup
grep -r ".init.setup" 
 __setup_start = .; *(.init.setup) __setup_end = .
//在源码中搜索__setup_start 
parse_args("Booting kernel", static_command_line, __start___param,
           __stop___param - __start___param,
           &unknown_bootoption);
    obsolete_checksetup(param)

static int __init obsolete_checksetup(char *line)
{
    struct obs_kernel_param *p;
    int had_early_param = 0;

    p = __setup_start;
    do {
        int n = strlen(p->str);
        if (!strncmp(line, p->str, n)) {
            if (p->early) {
                if (line[n] == '\0' || line[n] == '=')
                    had_early_param = 1;
            } else if (!p->setup_func) {
                printk(KERN_WARNING "Parameter %s is obsolete,"
                       " ignored\n", p->str);
                return 1;
            } else if (p->setup_func(line + n)) //最终调用这个setup_func
                return 1;
        }
        p++;
    } while (p < __setup_end);

//联系到前面:
static int __init root_dev_setup(char *line) 
//将/dev/mtdblock3拷贝到root_device_name 
void __init prepare_namespace(void)
        if (saved_root_name[0]) {
            root_device_name = saved_root_name;
            if (!strncmp(root_device_name, "mtd", 3) ||
                !strncmp(root_device_name, "ubi", 3)) {
                mount_block_root(root_device_name, root_mountflags);
            goto out;
        }
            ROOT_DEV = name_to_dev_t(root_device_name); //执行到这里
            if (strncmp(root_device_name, "/dev/", 5) == 0)
                root_device_name += 5;
    }
    initrd_load()
        handle_initrd();
            real_root_dev = new_encode_dev(ROOT_DEV);
            create_dev("/dev/root.old", Root_RAM0);
            pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
            mount_root();//执行挂载
//先将/dev/ram0挂载,而后执行/linuxrc.等其执行完后。切换根目录,再挂载具体的根文件系统.      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值