Android启动流程分析之三:内核启动过程2--start_kernel

http://blog.csdn.net/ly890700/article/details/54586484

 

start_kernel是内核启动后执行的第一个C语言函数,位于kernel/init/main.c中

一 start_kernel上半段

kernel/init/main.c Collapse source

asmlinkage __visible void __init start_kernel(void)

{

    char *command_line;

    char *after_dashes;

    /*

     * Need to run as early as possible, to initialize the

     * lockdep hash:

     */

    lockdep_init();

    set_task_stack_end_magic(&init_task);

    smp_setup_processor_id();

    debug_objects_early_init();

    cgroup_init_early();

    local_irq_disable();

    early_boot_irqs_disabled = true;

/*

 * Interrupts are still disabled. Do necessary setups, then

 * enable them

 */

    boot_cpu_init();

    page_address_init();

    pr_notice("%s", linux_banner);

    setup_arch(&command_line);

    /*

     * Set up the the initial canary ASAP:

     */

    boot_init_stack_canary();

    mm_init_cpumask(&init_mm);

    setup_command_line(command_line);

    setup_nr_cpu_ids();

    setup_per_cpu_areas();

    smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */

    build_all_zonelists(NULL, NULL);

    page_alloc_init();

    pr_notice("Kernel command line: %s\n", boot_command_line);

    parse_early_param();

    after_dashes = parse_args("Booting kernel",

                  static_command_line, __start___param,

                  __stop___param - __start___param,

                  -1, -1, &unknown_bootoption);

    if (!IS_ERR_OR_NULL(after_dashes))

        parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,

               set_init_arg);

    jump_label_init();

    /*

     * These use large bootmem allocations and must precede

     * kmem_cache_init()

     */

    setup_log_buf(0);

    pidhash_init();

    vfs_caches_init_early();

    sort_main_extable();

    trap_init();

    mm_init();

    /*

     * 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();

    /*

     * Disable preemption - early bootup scheduling is extremely

     * fragile until we cpu_idle() for the first time.

     */

    preempt_disable();

    if (WARN(!irqs_disabled(),

         "Interrupts were enabled *very* early, fixing it\n"))

        local_irq_disable();

    idr_init_cache();

    rcu_init();

    context_tracking_init();

    radix_tree_init();

    /* init some links before init_ISA_irqs() */

    early_irq_init();

    init_IRQ();

    tick_init();

    rcu_init_nohz();

    init_timers();

    hrtimers_init();

    softirq_init();

    timekeeping_init();

    time_init();

    sched_clock_postinit();

    perf_event_init();

    profile_init();

    call_function_init();

    WARN(!irqs_disabled(), "Interrupts were enabled early\n");

    early_boot_irqs_disabled = false;

    local_irq_enable();

在start_kernel上半段中会调用一系列初始化函数来完成内核的初始化工作:

1 lockdep_init();  初始化内核死锁检测机制的哈希表

2 smp_setup_processor_id();  返回cpu号,单核cpu返回0

3 debug_objects_early_init();  对调试对象进行早期的初始化

4 local_irq_disable();  关闭当前cpu的中断

5 boot_cpu_init();  设置当前cpu位激活状态

6 page_address_init();   初始化高端内存的

7 setup_arch(&command_line);  执行内核架构相关初始化函数

8 boot_init_stack_canary();  初始化栈canary值,canary值用于防止栈溢出攻击的堆栈的保护字

9 build_all_zonelists(NULL, NULL);  建立系统内存页区(zone)链表

10 page_alloc_init();  内存页初始化

11 在parse_args函数中解析cmdline中的启动参数

12 etup_log_buf(0);  使用memblock_alloc分配一个启动时log缓冲区

13 pidhash_init();  初始化pid散列表

14 vfs_caches_init_early();  初始化dentry和inode的hashtable

15 sort_main_extable();  对内核异常向量表进行排序

16 trap_init();  对内核陷阱异常进行初始化,arm没有用到

17 mm_init();  初始化内核内存分配器,过度到伙伴系统,启动slab机制,初始化非连续内存区

18 sched_init();  初始化进程调度器

19 local_irq_disable();  关闭本地中断

20 rcu_init();  初始化rcu机制

21 init_IRQ();  初始化中断lockdep_init

22 tick_init();  初始化时钟滴答控制器

23 init_timers();  初始化内核定时器

24 softirq_init();  初始化软中断

25 time_init();  时钟初始化

26 profile_init();   对内核的一个性能测试工具profile进行初始化

27 local_irq_enable();  使能当前cpu中断

 

二 start_kernel下半段

 

 

 

kernel/init/main.c Collapse source

    kmem_cache_init_late();

    /*

     * 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();

    if (panic_later)

        panic("Too many boot %s vars at `%s'", panic_later,

              panic_param);

    lockdep_info();

    /*

     * 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_INITRD

    if (initrd_start && !initrd_below_start_ok &&

        page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {

        pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",

            page_to_pfn(virt_to_page((void *)initrd_start)),

            min_low_pfn);

        initrd_start = 0;

    }

#endif

    page_cgroup_init();

    debug_objects_mem_init();

    kmemleak_init();

    setup_per_cpu_pageset();

    numa_policy_init();

    if (late_time_init)

        late_time_init();

    sched_clock_init();

    calibrate_delay();

    pidmap_init();

    anon_vma_init();

    acpi_early_init();

#ifdef CONFIG_X86

    if (efi_enabled(EFI_RUNTIME_SERVICES))

        efi_enter_virtual_mode();

#endif

#ifdef CONFIG_X86_ESPFIX64

    /* Should be run before the first non-init thread is created */

    init_espfix_bsp();

#endif

    thread_info_cache_init();

    cred_init();

    fork_init(totalram_pages);

    proc_caches_init();

    buffer_init();

    key_init();

    security_init();

    dbg_late_init();

    vfs_caches_init(totalram_pages);

    signals_init();

    /* rootfs populating might need page-writeback */

    page_writeback_init();

    proc_root_init();

    cgroup_init();

    cpuset_init();

    taskstats_init_early();

    delayacct_init();

    check_bugs();

    acpi_subsystem_init();

    sfi_init_late();

    if (efi_enabled(EFI_RUNTIME_SERVICES)) {

        efi_late_init();

        efi_free_boot_services();

    }

    ftrace_init();

    /* Do the rest non-__init'ed, we're now alive */

    rest_init();

}

 

在下半段中主要完成:

 

1 kmem_cache_init_late();  初始化slab分配器的缓存机制

 

2 console_init(); 初始化控制台

 

3 lockdep_info();  打印锁的依赖信息

 

4 locking_selftest();  死锁检测

5 page_cgroup_init();  为page_cgroup相关结构分配存储空间

6 debug_objects_mem_init();  创建debug_obj的slab高速缓存

你可能感兴趣的:(little,kernel)