setup_arch函数分析

注:内核版本Linux-2.6.39.4 开发板:MINI2440 ]

setup_arch执行是由start_kernel来调用的:

start_kernel [ init/main.c ] --> setup_arch(&command_line) [arch/arm/kernel/setup.c ]  

 799 void __init setup_arch(char **cmdline_p)
 800 {
 801         struct tag *tags = (struct tag *)&init_tags;
 802         struct machine_desc *mdesc;
 803         char *from = default_command_line;
 804 
 805         init_tags.mem.start = PHYS_OFFSET;
 806 
 807         unwind_init();
 808 
 809         setup_processor();
 810         mdesc = setup_machine(machine_arch_type);
 811         machine_desc = mdesc;
 812         machine_name = mdesc->name;
 813 
 814         if (mdesc->soft_reboot)
 815                 reboot_setup("s");
 816 
 817         if (__atags_pointer)
 818                 tags = phys_to_virt(__atags_pointer);
 819         else if (mdesc->boot_params) {
 820 #ifdef CONFIG_MMU
 821                 /*
 822                  * We still are executing with a minimal MMU mapping created
 823                  * with the presumption that the machine default for this
 824                  * is located in the first MB of RAM.  Anything else will
 825                  * fault and silently hang the kernel at this point.
 826                  */
 827                 if (mdesc->boot_params < PHYS_OFFSET ||
 828                     mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
 829                         printk(KERN_WARNING
 830                                "Default boot params at physical 0x%08lx out of reach\n",
 831                                mdesc->boot_params);
 832                 } else
 833 #endif
 834                 {
 835                         tags = phys_to_virt(mdesc->boot_params);
 836                 }
 837         }
 838 
 839 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
 840         /*
841          * If we have the old style parameters, convert them to
 842          * a tag list.
 843          */
 844         if (tags->hdr.tag != ATAG_CORE)
 845                 convert_to_tag_list(tags);
 846 #endif
 847         if (tags->hdr.tag != ATAG_CORE)
 848                 tags = (struct tag *)&init_tags;
 849 
 850         if (mdesc->fixup)
 851                 mdesc->fixup(mdesc, tags, &from, &meminfo);
 852 
 853         if (tags->hdr.tag == ATAG_CORE) {
 854                 if (meminfo.nr_banks != 0)
 855                         squash_mem_tags(tags);
 856                 save_atags(tags);
 857                 parse_tags(tags);
 858         }
 859 
 860         init_mm.start_code = (unsigned long) _text;
 861         init_mm.end_code   = (unsigned long) _etext;
 862         init_mm.end_data   = (unsigned long) _edata;
 863         init_mm.brk        = (unsigned long) _end;
 864 
 865         /* parse_early_param needs a boot_command_line */
 866         strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
 867 
 868         /* populate cmd_line too for later use, preserving boot_command_line */
 869         strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
 870         *cmdline_p = cmd_line;
 871 
 872         parse_early_param();
 873 
 874         arm_memblock_init(&meminfo, mdesc);
 875 
 876         paging_init(mdesc);
 877         request_standard_resources(mdesc);
 878 
 879 #ifdef CONFIG_SMP
 880         if (is_smp())
 881                 smp_init_cpus();
 882 #endif
 883         reserve_crashkernel();
 884 
 885         cpu_init();
 886         tcm_init();
 887 
 888 #ifdef CONFIG_MULTI_IRQ_HANDLER
 889         handle_arch_irq = mdesc->handle_irq;
 890 #endif
 891 
 892 #ifdef CONFIG_VT
 893 #if defined(CONFIG_VGA_CONSOLE)
 894         conswitchp = &vga_con;
 895 #elif defined(CONFIG_DUMMY_CONSOLE)
 896         conswitchp = &dummy_con;
 897 #endif
 898 #endif
 899         early_trap_init();
 900 
 901         if (mdesc->init_early)
 902                 mdesc->init_early();
 903 }

以下进行逐行分析:

809行:检测处理器类型,并初始化处理器相关的底层变量。内核启动时的处理器信息(包括cache)就是通过这个函数打印的,例如:

CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177                  
CPU: VIVT data cache, VIVT instruction cache  

810行: mdese  为设备描述结构体,对于任何板子都定义了这样的一个结构体,在内核自解压完成以后内核会首先会进入 bl      __lookup_machine_type函数(在arch/arm/kernel/head.S中),检查machine_type是否匹配,如果不匹配会跳入__error_a函数(在arch/arm/kernel/head-common.S中),导致启动失败,失败时串口会停在Uncompressing Linux... done, booting the kernel.对于mini2440

此结构体定义在arch/arm/mach-s3c2440/mach-mini2440.c

677 MACHINE_START(MINI2440, "MINI2440")
678         /* Maintainer: Michel Pollet <buserror@gmail.com> */
679         .boot_params    = S3C2410_SDRAM_PA + 0x100,
680         .map_io         = mini2440_map_io,
681         .init_machine   = mini2440_init,
682         .init_irq       = s3c24xx_init_irq,
683         .timer          = &s3c24xx_timer,
684 MACHINE_END
用GDB调试,其值为:

(gdb) p	mdesc 
$1 = (struct machine_desc *) 0xc0022518
(gdb) p	*mdesc 
$2 = {nr = 1999, name = 0xc038616a "MINI2440", boot_params = 805306624,	nr_irqs = 0, video_start = 0, 
  video_end = 0, reserve_lp0 = 0, reserve_lp1 = 0, reserve_lp2 = 0, soft_reboot = 0, fixup = 0,	reserve = 0, 
  map_io = 0xc000dbfc <mini2440_map_io>, init_early = 0, init_irq = 0xc000dc84 <s3c24xx_init_irq>, 
  timer = 0xc0401d1c, init_machine = 0xc000d8d8 <mini2440_init>} 

835行,tags定义在801行,定义时让它指向init_tags,phys_to_virt()是一个宏,它让tags指向mdesc->boot_params(0xc0000100),也就是BootLoader传递过来的参数的地址

#define phys_to_virt(a) ((void *)(unsigned long)(a))
860-863行,这四个参数来自arch/arm/kernel/vmlinux.lds.S, 这里通过连接脚本中得到的Linux代码位置数据来初始化一个mm_struct结构体init_mm中的部分数据,每一个任务都有一个mm_struct结构以管理内存空间,init_mm是内核自身的mm_struct;

872行,解析cmdline,这里只解析了当中的mem部分,内核参数的解析一共有两处,一处是setup_arch()->parse_cmdline()用于解析内核参数中关于内存的部分,另外一处是start_kernel()->parse_option()用于解析其余部分

874行,在此处按地址数据从小到大排序meminfo中的数据,并初始化全局的memblock数据;

876行,设置内核的参考页表。此页表不仅用于物理内存映射,还用于管理vmalloc区此函数中非常重要的一点就是初始化了bootmem分配器!对于bootmem会有专门博文进行分析。

877行,通过获取设备描述结构体(struct machine_desc)中的数据和编译时产生的地址数据,初始化内存相关的全局结构体变量

885行,初始化一个CPU,并设置一个per-CPU栈;

886行,初始化ARM内部的TCM(紧耦合内存);

888-890行,注册irq函数;

892-899行,对中断向量进行早期初始化;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生参加学科竞赛有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞赛是提高专业知识和技能水平的有效途径。通过参与竞赛,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞赛过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞赛培养了学生的团队合作精神。许多竞赛项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞赛是提高学生综合能力的一种途径。竞赛项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参赛者具备全面的素质。在竞赛过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞赛可以为学生提供展示自我、树立信心的机会。通过比赛的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞赛对于个人职业发展具有积极的助推作用。在竞赛中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞赛奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值