嵌入式Linux——分析kernel运行过程(2):kernel第二阶段

2019-07-12 19:28发布

简介:

        本文主要介绍在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] = '