简介:
本文主要介绍在2.6.22.6版内核中,代码的运行过程。而在kernel的第二阶段主要介绍在内核代码中如何解析从u-boot和前面汇编代码中获得TAG参数与machine_desc结构体。
声明:
本文主要是看了韦东山老师的视频后所写,希望对你有所帮助。
u-boot版本 : u-boot-1.1.6
开发板 : JZ2440
Linux内核 : Linux-2.6.22.6
start_kernel :
从start_kernel函数开始,程序就是C语言代码了。而相较于前面的汇编代码,这里的C语言代码可以实现更加复杂的功能,同时也更好理解一些。我们知道内核要做的事有两件:第一件是挂载根文件系统,而第二件则是执行第一个应用程序。而内核挂载什么样的根文件系统,同时内核执行的第一个应用程序是什么?这些都是我们想要弄清楚的。同时我们在上面一篇文章:
嵌入式Linux——分析kernel运行过程(1):kernel第一阶段 中讲到了从u-boot向内核传入三个参数:0,单板对应的机器ID和TAG参数首地址。我们使用第二个参数——机器ID找到了与单板相关的结构体machine_desc。而从u-boot传入的TAG参数至今还没有使用,那么程序是否会在下面用到这些已知的信息那?我们看代码来慢慢了解这些(
initmain.c)。
我们初看start_kernel函数会觉得这个函数很大,同时内部的函数很多,但是如果我们带着上面的问题来看这些代码,并将那些没用的函数删除,那么start_kernel可以包含下面一些函数:
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern struct kernel_param __start___param[], __stop___param[];
printk(KERN_NOTICE);
printk(linux_banner);
setup_arch(&command_line);
setup_command_line(command_line);
page_alloc_init();
printk(KERN_NOTICE "Kernel command line: %s
", boot_command_line);
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
__stop___param - __start___param,
&unknown_bootoption);
/* Do the rest non-__init'ed, we're now alive */
rest_init();
}
而在上面的函数中主要做两件事:
1. 解析TAG参数与machine_desc结构体,获得单板信息
2. 挂接根文件系统以及执行第一个应用程序
解析TAG参数与machine_desc结构体主要由setup_arch函数和setup_command_line函数来完成。我们先看在setup_arch函数中做了什么样的设置(
archarmkernelsetup.c):
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc;
char *from = default_command_line;
setup_processor();
mdesc = setup_machine(machine_arch_type);
machine_name = mdesc->name;
if (mdesc->soft_reboot)
reboot_setup("s");
if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
/*
* If we have the old style parameters, convert them to
* a tag list.
*/
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;
if (mdesc->fixup)
mdesc->fixup(mdesc, tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
parse_tags(tags);
}
init_mm.start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
boot_command_line[COMMAND_LINE_SIZE-1] = '