我们再来分析一下rest_init()
首先要明确一下,u-boot的最终目的是为了启动内核,那么内核启动的目的又是什么呢?那就是运行应用程序,而应用程序是挂载在跟文件系统上的。其实rest_init()就是来启动应用程序的,好的,来看代码:
rest_init()里面调用kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND),而这个函数的含义可以理解为调用函数kernel_init()----->prepare_namespace()------>mount_root(),这个函数就用来挂接跟文件系统。挂载好跟文件系统后会回到kernel_init()函数里调用函数:init_post(),在init_post()函数里我们贴出一些代码来说明它的作用:
sys_open((const char __user *) "/dev/console", O_RDWR, 0) //打开控制台
run_init_process("/sbin/init");//执行应用程序
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
上面prepare_namespace()调用mount_root()来挂载跟文件系统,其实在挂载文件系统之前肯定还要根据具体的参数来确定挂载哪些文件系统,所以我们还是要在来分析一下prepare_namespace()函数:
我们贴出init/do_mounts.c文件里的下面几行代码
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的定义在include/linux/init.h中:
#define __setup(str, fn)
__setup_param(str, fn, fn, 0)
#define __setup_param(str, unique_id, fn, early)
static char __setup_str_##unique_id[] __initdata = str;
static struct obs_kernel_param __setup_##unique_id
__attribute_used__
__attribute__((__section__(".init.setup")))
__attribute__((aligned((sizeof(long)))))
= { __setup_str_##unique_id, fn, early }
以上就是定义了一个结构体,这个结构体里有一个字符串,一个函数,还有一个early,且这个结构体的段属性为.init.setup,查看连接脚本发现如下代码:
__setup_start = .;
*(.init.setup)
__setup_end = .;
说明所有的结构体被放在__setup_start 到__setup_end 之间。其实在解析命令行参数是,就会根据root=?来调用相应的处理程序!