首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

linux内核启动流程(上)

2013-03-21 
linux内核启动流程(下)接上回start_kernel在/init/main.c中定义asmlinkage void __init start_kernel(void

linux内核启动流程(下)
接上回start_kernel在/init/main.c中定义asmlinkage void __init start_kernel(void){char * command_line;extern struct kernel_param __start___param[], __stop___param[];
smp_setup_processor_id();
/* * Need to run as early as possible, to initialize the * lockdep hash: */unwind_init();        //Convert the symbol addresses to absolute valueslockdep_init();        //锁定入口,初始化散列/*void lockdep_init(void) {         int i;
         /*          * Some architectures have their own start_kernel()          * code which calls lockdep_init(), while we also          * call lockdep_init() from the start_kernel() itself,          * and we want to initialize the hashes only once:          */         if (lockdep_initialized)                 return;          for (i = 0; i < CLASSHASH_SIZE; i++)                 INIT_LIST_HEAD(classhash_table + i);          for (i = 0; i < CHAINHASH_SIZE; i++)                 INIT_LIST_HEAD(chainhash_table + i);          lockdep_initialized = 1; }*/cgroup_init_early();    //cgroup: 它的全称为control group.即一组进程的行为控制.该函数主要是做数据结构和其中链表的初始化
local_irq_disable();    //关闭系统总中断early_boot_irqs_off();    //设置系统中断的关闭标志early_init_irq_lock_class();
/* * Interrupts are still disabled. Do necessary setups, then * enable them */lock_kernel();tick_init();    //初始化内核时钟系统boot_cpu_init();    //激活当前cpu/*static void __init boot_cpu_init(void){int cpu = smp_processor_id();/* Mark the boot cpu "present", "online" etc for SMP and UP case */cpu_set(cpu, cpu_online_map);cpu_set(cpu, cpu_present_map);cpu_set(cpu, cpu_possible_map);}*/page_address_init();    //高端内存相关,未定义高端内存的话为空函数/*void __init page_address_init(void) {         int i;         INIT_LIST_HEAD(&page_address_pool);         for (i = 0; i < ARRAY_SIZE(page_address_maps); i++)                 list_add(&page_address_maps[i].list, &page_address_pool);         for (i = 0; i < ARRAY_SIZE(page_address_htable); i++) {                 INIT_LIST_HEAD(&page_address_htable[i].lh);                 spin_lock_init(&page_address_htable[i].lock);         }         spin_lock_init(&pool_lock); }*/printk(KERN_NOTICE);printk(linux_banner);    //将打印信息放在缓冲(4K),因为控制台还没初始化,系统起来后可以用dmesg查看setup_arch(&command_line);    //设置与体系结构相关的环境/*在arch/arm/kernel/setup.cvoid __init setup_arch(char **cmdline_p){struct tag *tags = (struct tag *)&init_tags;struct machine_desc *mdesc;char *from = default_command_line;
setup_processor();        //进行处理器相关的设置,会调用引导阶段的lookup_processor_type函数mdesc = setup_machine(machine_arch_type);    //获得开发板的machine_desc结构machine_name = mdesc->name;
if (mdesc->soft_reboot)reboot_setup("s");
if (__atags_pointer)            //tags列表的首地址,在arch/arm/mach-pxa/littleton.c中的MACHINE_START:.boot_params= 0xa0000100。tags = phys_to_virt(__atags_pointer);    //转换为虚拟地址else 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);     //如果已经在内核中定义了meminfo结构,则忽略内存tagsave_atags(tags);parse_tags(tags);    //处理每个tag//每个tag都定义了相对应的处理函数,比如内存tag,__tagtable(ATAG_MEM, parse_tag_mem32);}
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] = '\0';parse_cmdline(cmdline_p, from);    //对命令进行一些先期的处理,主要通过early_params结构体paging_init(&meminfo, mdesc);    //重新初始化页表,设置页表, 初始化内存映射,分配三页出来用于处理异常过程:零页面,坏页和坏页表。//paging_init-->devicemaps_init-->map_io 也就是.map_io= pxa_map_io。这里设置晶振频率request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMPsmp_init_cpus();#endif
cpu_init();        //cpu初始化
/* * Set up various architecture-specific pointers */init_arch_irq = mdesc->init_irq;system_timer = mdesc->timer;init_machine = mdesc->init_machine;
#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE)conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE)conswitchp = &dummy_con;#endif#endif}*/setup_command_line(command_line);    //对cmdline进行备份和保存unwind_setup();setup_per_cpu_areas();    //为系统中每个处理器的per_cpu变量申请空间smp_prepare_boot_cpu();/* arch-specific boot-cpu hooks */针对SMP处理器的内存初始化函数
/* * Set up the scheduler prior starting any interrupts (such as the * timer interrupt). Full topology setup happens at smp_init() * time - but meanwhile we still have a functioning scheduler. */sched_init();    //初始化每个处理器的可运行进程队列,设置系统初始化进程即0号进程/* * Disable preemption - early bootup scheduling is extremely * fragile until we cpu_idle() for the first time. */preempt_disable();build_all_zonelists();    //建立系统内存页区链表page_alloc_init();printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);parse_early_param();    //解析早期格式内核参数parse_args("Booting kernel", static_command_line, __start___param,   __stop___param - __start___param,    //解析新格式内核参数   &unknown_bootoption);        //命令行的后续处理,在kernel\include\asm-generic\vmlinux.lds.h有关kernel_param的结构体if (!irqs_disabled()) {printk(KERN_WARNING "start_kernel(): bug: interrupts were ""enabled *very* early, fixing it\n");local_irq_disable();}sort_main_extable();//将放在__start__ex_table到__stop__ex_table之间的*(__ex_table)区中的struct exception_table_entry型全局结构变量按insn成员变量值从小到大排序,即将可能导致缺页异常的指令按其指令二进制代码值从小到大排序trap_init();    //异常入口地址搬到高端中断向量rcu_init();    //Read-Copy Update,RCU锁机制初始化init_IRQ();pidhash_init();     //根据内存大小设置pid hash列表init_timers();hrtimers_init();softirq_init();timekeeping_init();time_init();profile_init();        //对体统剖析做相关初始化if (!irqs_disabled())printk("start_kernel(): bug: interrupts were enabled early\n");early_boot_irqs_on();local_irq_enable();
/* * HACK ALERT! This is early. We're enabling the console before * we've done PCI setups etc, and console_init() must be aware of * this. But we do want output early, in case something goes wrong. */console_init();/*在drivers/char/tty_io.c中void __init console_init(void){initcall_t *call;
/* Setup the default TTY line discipline. */(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
/* * set up the console device so that later boot sequences can * inform about problems etc.. */call = __con_initcall_start;while (call < __con_initcall_end) {(*call)();call++;}}它调用的范围从con_initcall_start到con_initcall_end之间定义的每个函数,这些函数使用console_initcall宏来指定。*/if (panic_later)panic(panic_later, panic_param);
lockdep_info();    //lockdep是一个内核调试模块,用来检测内核互斥机制潜在的死锁问题
/* * Need to run this when irqs are enabled, because it wants * to self-test [hard/soft]-irqs on/off lock inversion bugs * too: */locking_selftest();
#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start && !initrd_below_start_ok &&initrd_start < min_low_pfn << PAGE_SHIFT) {printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "    "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);initrd_start = 0;}#endifvfs_caches_init_early();cpuset_init_early();mem_init();    //初始化内存,调节内存申请限制enable_debug_pagealloc();cpu_hotplug_init();kmem_cache_init();    //执行高速缓存内存管理,即slab分配器相关初始化setup_per_cpu_pageset();numa_policy_init();if (late_time_init)late_time_init();calibrate_delay();    //计算bogoMIPS值,一个衡量cpu性能的标志pidmap_init();        //PID分配映射初始化pgtable_cache_init();prio_tree_init();anon_vma_init();    //匿名虚拟内存域初始化#ifdef CONFIG_X86if (efi_enabled)efi_enter_virtual_mode();#endiffork_init(num_physpages);    //进程创建机制初始化,为内核“task_struct”分配空间,计算最大任务数proc_caches_init();    //初始化进程创建机制所需的其他数据结构,为其申请空间buffer_init();    //缓存系统初始化,创建缓存头空间,并检查其大小unnamed_dev_init();    key_init();    //内核密钥管理体统初始化security_init();    //内核安全框架初始化vfs_caches_init(num_physpages);    //虚拟文件系统缓存初始化radix_tree_init();signals_init();    //信号管理系统初始化/* rootfs populating might need page-writeback */page_writeback_init();    //页写回机制初始化#ifdef CONFIG_PROC_FSproc_root_init();    //proc文件系统初始化#endifcgroup_init();    //control group正式初始化cpuset_init();    //CPUSET初始化taskstats_init_early();    //任务状态早期初始化函数,为结构体获取高速缓存,并初始化互斥机制delayacct_init();    //任务延迟机制初始化
check_bugs();    //检测cpu bug函数
acpi_early_init(); /* before LAPIC and SMP init */
/* Do the rest non-__init'ed, we're now alive */rest_init();    //剩余的初始化}
小结:1.内核启动参数的获取和处理2.内存管理的初始化


热点排行