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高速缓存


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值