Linux内核源码分析_setup_arch函数的主要作用
2015-03-10 16:40
417 查看
`一、setup_arch函数的主要作用
在start_kernel中,调用setup_arch函数,传给他的参数是那个未被初始化的内部变量command_line。这个setup_arch()函数是start_kernel阶段最重要的一个函数,每个体系都有自己的setup_arch()函数,是体系结构相关的,具体编译哪个体系的setup_arch()函数,由顶层Makefile中的ARCH变量决定:它首先通过检测出来的处理器类型进行处理器内核的初始化,然后通过
bootmem_init()函数根据系统定义的
meminfo 结构进行内存结构的初始化,最后调用paging_init()开启
MMU,创建内核页表,映射所有的物理内存和
IO空间。
start_kernel () --> setup_arch () --> paging_init () --> bootmem_init () --> alloc_bootmem_low_pages ()
具体代码分析如下:
void __init setup_arch(char **cmdline_p) { struct tag *tags = (struct tag *)&init_tags; //定义了一个默认的内核参数列表 struct machine_desc *mdesc; //设备描述的结构体 char *from = default_command_line; init_tags.mem.start = PHYS_OFFSET; unwind_init(); setup_processor(); //汇编的CPU初始化部分 mdesc = setup_machine(machine_arch_type); machine_desc = mdesc; machine_name = mdesc->name; //下面一部分通过匹配struct machine_desc结构体数据,初始化一些全局变量 //通过struct machine_desc 中的soft_reboot设置重启类型 if (mdesc->soft_reboot) reboot_setup("s"); //检查bootloader是否传入参数,如果传入,则给tags赋值,若果没有传入则传递默认的启动参数地址 if (__atags_pointer) tags = phys_to_virt(__atags_pointer); else if (mdesc->boot_params) { #ifdef CONFIG_MMU /* * We still are executing with a minimal MMU mapping created * with the presumption that the machine default for this * is located in the first MB of RAM. Anything else will * fault and silently hang the kernel at this point. */ if (mdesc->boot_params < PHYS_OFFSET || mdesc->boot_params >= PHYS_OFFSET + SZ_1M) { printk(KERN_WARNING "Default boot params at physical 0x%08lx out of reach\n", mdesc->boot_params); } else #endif { tags = phys_to_virt(mdesc->boot_params); } } #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) /* * If we have the old style parameters, convert them to * a tag list. */ if (tags->hdr.tag != ATAG_CORE) //内核参数列表第一项为ATAG_CORE convert_to_tag_list(tags); //如果不是,这需要转换成新的内核参数类型,新的内核参数类型用下面的structtag结构表示 #endif if (tags->hdr.tag != ATAG_CORE) tags = (struct tag *)&init_tags; //如果没有内核参数,则选用默认的内核参数,在init_tags文件中有定义 if (mdesc->fixup) mdesc->fixup(mdesc, tags, &from, &meminfo); //用选用的内核参数列表填充meminfo ,fixup函数出现在注册machine_desc中,即MACHINE_START、MACHINE_END定义中,这个函数,有些板子有,但在2410中没有定义这个函数。 if (tags->hdr.tag == ATAG_CORE) { if (meminfo.nr_banks != 0) //如果内存被初始化过 squash_mem_tags(tags); //如果是tag list,那么如果系统已经创建了默认的meminfo.nr_banks,清除tags中关于MEM的参数,以免再次被初始化 save_atags(tags); parse_tags(tags); //做一些针对各个tags的处理 } //解析内核参数列表,然后调用内核参数列表的处理函数对这些参数进行处理。比如,如果列表为命令行,则最终会用parse_tag_cmdlin函数进行解析,这个函数用_tagtable编译连接到了内核里 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; //记录了内核代码的起始,结束虚拟地址 /* parse_early_param needs a boot_command_line */ strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); /* populate cmd_line too for later use, preserving boot_command_line */ strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = cmd_line; //将boot_command_line复制到cmd_line中 parse_early_param(); //解释命令行参数 arm_memblock_init(&meminfo, mdesc); //将设备实体登记注册到总线空间链表中去 paging_init(mdesc); request_standard_resources(mdesc); #ifdef CONFIG_SMP if (is_smp()) smp_init_cpus(); //要配置CONFIG_KEXEC,否则为空函数,2410中没有配置 #endif reserve_crashkernel(); cpu_init(); //初始化一个CPU,并设置一个per-CPU栈 tcm_init(); //初始化ARM内部的TCM(紧耦合内存) #ifdef CONFIG_MULTI_IRQ_HANDLER handle_arch_irq = mdesc->handle_irq; #endif #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif #endif early_trap_init(); //对中断向量表进行早期的初始化 //如果设备描述结构体定义了init_early函数(应该是早期初始化之意),则在这里调用 if (mdesc->init_early) mdesc->init_early(); }
参考网址:
http://blog.csdn.net/boarmy/article/details/8652343
http://www.wesage.net/bbs/forum.php?mod=viewthread&tid=212&page=1
相关文章推荐
- linux内核启动第二阶段之setup_arch()函数分析-2.6.36
- linux内核启动第二阶段之setup_arch()函数分析-2.6.36
- linux内核启动第二阶段分析-setup_arch()函数
- linux内核启动第二阶段之setup_arch()函数分析-2.6.36
- linux内核启动第二阶段之setup_arch()函数分析-2.6.36
- linux内核启动第二阶段分析-setup_arch()函数
- 29、(8)Linux内核启动第二阶段之 setup_arch函数分析
- linux内核起动1-启动参数(启动参数的获取和处理,分析setup_arch)
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析
- Linux内核源码分析--内存管理(二、函数实现技巧)
- setup_arch()函数分析4--cpu_init
- setup_arch()函数分析4--cpu_init
- linux 3.6 启动源码分析(三) setup_arch
- [置顶] linux内核启动2-setup_arch中的内存初始化(目前分析高端内存)
- Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】
- linux-3.2.36内核启动4-setup_arch中的内存初始化3(arm平台 bootmem_init源码分析)
- (二)start_kernel分析二---之setup_arch()函数分析
- setup_arch()函数分析5--early_trap_init
- linux-3.2.36内核启动4-setup_arch中的内存初始化3(arm平台 bootmem_init源码分析)