1、流程:
内核启动-->初始化-->建立进程0-->启动文件描述符0、1、2(标准输入文件\标准输出文件\标准错误输出文件)-->
函数流程
start_kernel(void)-->rest_init(void)-->kernel_init(void * unused)-->init_post(void)-->
函数内容如下,标号②尝试执行默认的初始化命令行程序,若失败则执行标号③的初始化程序,仍然失败则提示④,意味着根文件系统内没有初始化程序用于执行。
if (ramdisk_execute_command) {
① run_init_process(ramdisk_execute_command);
printk(KERN_WARNING "Failed to execute %s\n",
ramdisk_execute_command);
}
if (execute_command) {
② run_init_process(execute_command);
printk(KERN_WARNING "Failed to execute %s. Attempting "
"defaults...\n", execute_command);
}
③ run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");
④ panic("No init found. Try passing init= option to kernel. "
"See Linux Documentation/init.txt for guidance.");
查找execute_command的值。在init_setup(char *str)函数中被赋值
static int __init init_setup(char *str)
{
unsigned int i;
execute_command = str;
for (i = 1; i < MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
__setup("init=", init_setup);
__setup("init=", init_setup);定义如下(init.h),把形参保存在struct obs_kernel_param结构体内,并放在了.init.setup段内。
struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
int early;
};
#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 }
#define __setup(str, fn) \
__setup_param(str, fn, fn, 0)
结构体参数初始化为"init=",init_setup,0。
此参数被使用的流程start_kernel(void)-->parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);-->unknown_bootoption(char *param, char *val)-->obsolete_checksetup(char *line)在此函数内执行了init_setup函数完成了对execute_command的赋值。过程如下
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) {
/* Already done in parse_early_param?
* (Needs exact match on param part).
* Keep iterating, as we can have early
* params and __setups of same names 8( */
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))
return 1;
}
p++;
} while (p < __setup_end);
return had_early_param;
}
p->setup_func(line + n)就是执行init_setup()函数,参数就是uboot传递给 kernel的参数中“init=xxx”其中的xxx字符串。内核会将此字符串作为run_init_process(execute_command);的参数去执行对应的初始化程序。这个初始化程序一般由busybox提供,一般为linuxrc。
总结:
内核启动后挂载根文件系统,在指定目录下找到初始化程序,执行初始化操作。
在制作根文件系统时必须要有linuxrc初始化程序