嵌入式 hi3518c内核start_kernel函数小议

我们先来看源码,有代码才有说服力哦:


1.asmlinkage void __init start_kernel(void)

2. {

3.     char * command_line;

4.     extern const struct kernel_param __start___param[], __stop___param[];

5. 

6.     smp_setup_processor_id(); //确定SMP系统中每个CPU的id

7. 

8.     /*

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

10.      * lockdep hash:

11.      */

12.     lockdep_init(); //初始化互斥锁的dependency。

13.     debug_objects_early_init(); //初始化debug kernel相关

14. 

15.     /*

16.      * Set up the the initial canary ASAP:

17.      */

18.     boot_init_stack_canary(); //stack_canary的是带防止栈溢出攻击保护的堆栈。

19. 

20.     cgroup_init_early(); //cgroup是什么??有待查找

21. 

22.     local_irq_disable(); //这个太直白了。

23.     early_boot_irqs_off(); //这个也很直白。

24. 

25. /*

26.  * Interrupts are still disabled. Do necessary setups, then

27.  * enable them

28.  */

29.     tick_init(); //初始化time ticket,时钟

30.     boot_cpu_init(); //用以启动的CPU进行初始化。也就是初始化CPU0

31.     page_address_init();//初始化页面

32.     printk(KERN_NOTICE "%s", linux_banner);

33.     setup_arch(&command_line); //CPU架构相关的初始化

34.     mm_init_owner(&init_mm, &init_task); //初始化内存管理

35.     setup_command_line(command_line); //处理启动命令行

36.     setup_nr_cpu_ids(); //nr_cpu_id是什么?

37.     setup_per_cpu_areas(); //为每个CPU开辟一块区域?

38.     smp_prepare_boot_cpu();//准备boot_cpu.   /* arch-specific boot-cpu hooks */ 

39. 

40.     build_all_zonelists(NULL); //建立什么样的zone??

41.     page_alloc_init(); //初始化page allocation相关结构

42. 

43.     printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);

44.     parse_early_param(); 

45.     parse_args("Booting kernel", static_command_line, __start___param,

46.          __stop___param - __start___param,

47.          &unknown_bootoption);//解析启动参数

48.     /*

49.      * These use large bootmem allocations and must precede

50.      * kmem_cache_init()

51.      */

52.     pidhash_init();//初始化process ID hash表

53.     vfs_caches_init_early(); //文件系统caches预初始化

54.     sort_main_extable(); //初始化exception table

55.     trap_init(); //初始化trap,用以处理错误执行代码

56.     mm_init(); //初始化内存管理

57.     /*

58.      * Set up the scheduler prior starting any interrupts (such as the

59.      * timer interrupt). Full topology setup happens at smp_init()

60.      * time - but meanwhile we still have a functioning scheduler.

61.      */

62.     sched_init(); //进程调度初始化

63.     /*

64.      * Disable preemption - early bootup scheduling is extremely

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

66.      */

67.     preempt_disable(); //这个是什么东东?

68.     if (!irqs_disabled()) {

69.         printk(KERN_WARNING "start_kernel(): bug: interrupts were "

70.                 "enabled *very* early, fixing it\n");

71.         local_irq_disable();

72.     }

73.     rcu_init(); //Read_Copy_Update机制初始

74.     radix_tree_init(); //什么是radlx_tree

75.     /* init some links before init_ISA_irqs() */

76.     early_irq_init();

77.     init_IRQ(); //初始化中断

78.     prio_tree_init(); //这是啥?以后要弄懂

79.     init_timers(); //初始化时钟

80.     hrtimers_init();//初始化高精时钟

81.     softirq_init();//初始化软中断

82.     timekeeping_init();//初始化时钟源

83.     time_init();//初始化时间例程

84.     profile_init(); //Profile?这是什么profile?

85.     if (!irqs_disabled())

86.         printk(KERN_CRIT "start_kernel(): bug: interrupts were "

87.                  "enabled early\n");

88.     early_boot_irqs_on();

89.     local_irq_enable();

90. 

91.     /* Interrupts are enabled now so all GFP allocations are safe. */

92.     gfp_allowed_mask = __GFP_BITS_MASK;

93. 

94.     kmem_cache_init_late();//初始化CPU Cache

95. 

96.     /*

97.      * HACK ALERT! This is early. We're enabling the console before

98.      * we've done PCI setups etc, and console_init() must be aware of

99.      * this. But we do want output early, in case something goes wrong.

100.      */

101.     console_init(); //初始化console

102.     if (panic_later)

103.         panic(panic_later, panic_param);

104. 

105.     lockdep_info();

106. 

107.     /*

108.      * Need to run this when irqs are enabled, because it wants

109.      * to self-test [hard/soft]-irqs on/off lock inversion bugs

110.      * too:

111.      */

112.     locking_selftest(); //自测试锁

113. 

114. #ifdef CONFIG_BLK_DEV_INITRD

115.     if (initrd_start && !initrd_below_start_ok &&

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

117.         printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "

118.          "disabling it.\n",

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

120.          min_low_pfn);

121.         initrd_start = 0;

122.     }

123. #endif

124.     page_cgroup_init(); //页面初始

125.     enable_debug_pagealloc(); //页面分配debug启用

126.     kmemleak_init(); //memory leak 侦测初始化

127.     debug_objects_mem_init(); //debug object是什么?

128.     idr_init_cache(); //idr是什么? 

129.     setup_per_cpu_pageset(); //设置每个CPU的页面集合

130.     numa_policy_init();// NUMA (Non Uniform Memory Access) policy 
131.     if (late_time_init)

132.         late_time_init();

133.     sched_clock_init();//初始化调度时钟

134.     calibrate_delay(); //协同不同CPU的时钟
135.     pidmap_init();//pid是process id还是processor id?

136.     anon_vma_init();//anonymous page?什么意思?

137. #ifdef CONFIG_X86

138.     if (efi_enabled)

139.         efi_enter_virtual_mode();

140. #endif

141.     thread_info_cache_init(); //初始化thread info

142.     cred_init(); //credential

143.     fork_init(totalram_pages); //初始化fork

144.     proc_caches_init(); //初始化/proc的cache?

145.     buffer_init(); // buffer

146.     key_init(); //key

147.     security_init();//security

148.     dbg_late_init();//debug

149.     vfs_caches_init(totalram_pages);//文件系统cache初始化

150.     signals_init();//signal

151.     /* rootfs populating might need page-writeback */

152.     page_writeback_init();page_writeback

153. #ifdef CONFIG_PROC_FS

154.     proc_root_init();

155. #endif

156.     cgroup_init(); //cgroup?

157.     cpuset_init(); //cpuset

158.     taskstats_init_early(); //task

159.     delayacct_init();

160. 

161.     check_bugs(); //检查什么bug?

162. 

163.     acpi_early_init();//acpi /* before LAPIC and SMP init */ 

164.     sfi_init_late(); //simple firmware interface

165. 

166.     ftrace_init();

167. 

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

169.     rest_init();

170. }


 

下面进行一下重要函数的解析:

start_kernel()函数位于init/main.c中,是引导过程中最重要的一个函数,就像它的名字一样,它初始化了内核所有的功能。
   1,调用lock_kernel(),防止内核被意外抢断,定义在lib/kernel_lock.c中。在SMP或者抢断式调度环境中,内核可以被抢断。内核初始化时,功能还不完善,为防止此种情况发生,使用称为Big Kernel Lock的spinlock。spinlock是一种忙等待锁,如果等待周期不是很长,它比信号有效,因为信号会造成进程调度。Big Kernel Lock只在内核初始化时使用,当初始化结束后,该锁被释放。
   2,page_address_init()函数初始化页管理,创建了页管理所需的数据结构,定义在mm/highmem.c中。
   3,输出内核版本信息,执行了两个内核输出语句printk(KERN_NOTICE)和printk(linux_banner)。因为此时还没有初始化控制台,所以这些信息不能输出到屏幕上或者输出到串口上,而是输出到一个buffer中。printk()函数定义在kernel/printk.c 中,KERN_NOTICE宏定义在include/linux/kernel.h中,值为"<5>"。linux_banner定义在 init/version.c中,在我的实验环境中是这样的一个字符串:Linux version 2.6.28 (zctan@dbgkrnl) (gcc version 4.3.0 20080428 (Red Hat 4.3.0-8) (GCC) ) #1 SMP Sun Feb 8 20:56:17 CST 2009。
   4,setup_arch(),位于arch/x86/kernel/setup.c,初始化了许多体系结构相关的子系统。
   5,setup_per_cpu_area(),定义在arch/x86/kernel/setup_percpu.c中,如果是SMP环境,则为每个CPU创建数据结构,分配初始工作内存。
   6,smp_prepare_boot_cpu(),定义在include/asm-x86/smp.h。如果是SMP环境,则设置boot CPU的一些数据。在引导过程中使用的CPU称为boot CPU。
   7,sched_init(),定义在kernel/sched.c。初始化每个CPU的运行队列和超时队列。Linux使用多优先级队列的调度方法,就绪进程位于运行队列中。
   8,build_all_zonelists(),定义在mm/page_alloc.c中,建立内存区域链表。Linux将所有物理内存分为三个区,ZONE_DMA, ZONE_NORMAM, ZONE_HIGHMEM。
   9,trap_init(),定义在arch/x86/kernel/traps_32.c中,初始化IDT, 如除0错,缺页中断等。
   10,rcu_init(),定义在kernel/rcupdate.c中,初始化Read-Copy-Update子系统。当使用spinlock会造成效率低下时,RCU被用来实现临界区的互斥。
   11,init_IRQ(),定义在arch/x86/kernel/paravirt.c中,初始化中断控制器。
   12,pidhash_init(),定义在kernel/pid.c中,Linux的进程描述符称为PID, 使用名称空间以及hash表来管理。
   13,init_timers(),定义在kernel/timer.c中,初始化定时器。
   14,softirq_init(),定义在kernel/softirq.c中,初始化中断子系统,如softirq, tasklet。
   15,time_init(),定义在arch/x86/kernel/time_32.c中,初始化系统时间。
   16,profile_init(),定义在kernel/profile.c中,为profiling data分配存储空间。Profiling data这个术语描述在程序运行过程中采集到的一些数据,用于性能的分析。
   17,local_irq_enable(),定义在include/linux/irqflags.h中,开启引导CPU的中断。
   18,console_init(),定义在drivers/char/tty_io.c中,初始化控制台,可以是显示器也可以是串口。此时屏幕上才会有输出,前面printk输出到buffer中的内容会在这里全部输出。
   19,initrd检测。如果定义了Init Ram Disk,则检测其是否有效。
   20,mem_init(),定义在arch/x86/mm/init_32.c,检测所有可用物理页。
   21,pgtable_cache_init(),定义在include/asm-x86/pgtable_32.h,在slab存储管理子系统中创建页目录页表的cache。
   22,fork_init(),定义在kernel/fork.c中,初始化多进程环境。此时,执行start_kernel的进程就是所谓的进程0。
   23,buffer_init(),定义在fs/buffer.c中,初始化文件系统的缓冲区。
   24,vfs_cache_init(),定义在fs/dcache.c中,创建虚拟文件系统的Slab Cache。
   25,radix_tree_init(),定义在lib/radix-tree.c。Linux使用radix树来管理位于文件系统缓冲区中的磁盘块,radix树是trie树的一种。
   26,signals_init(),定义在kernel/signal.c中,初始化信号队列。
   27,page_writeback_init(),定义在mm/page-writeback.c中,初始化将脏页页同步到磁盘上的控制信息。
   28,proc_root_init(),定义在fs/proc/root.c, 初始化proc文件系统
   29,rest_init(),定义在init/main.c中,创建init内核线程(也就是进程1)。init进程创建成功后,进程0释放Big Kernel Lock,重新调度(因为现在只有两个进程,所以调度的是init进程)。进程0,就变成了idle进程,只负责调度。
   注:start_kernel函数涉及到很多内容和硬件知识,比如SMP等,有很多是我不知道的,所以只能简要的从功能上说明一下,有些可能理解错了,也会略过一些函数,请见谅。
  六,init进程
   init进程执行定义在init/main.c中的kernel_init()函数,完成余下的初始化工作。
   1,lock_kernel(),加上Big Kernel Lock。
   2,初始化SMP环境。
   3,do_basic_setup()。调用driver_init(),加载设备驱动程序。执行do_initcalls(),调用内建模块的初始化函数,比如kgdb。
   4,init_post()函数会打开/dev/console做为标准输入文件,并复制出标准输出和标准错误输出。最后,按下列顺序偿试执行init程序,位于ramdisk的/init,以及磁盘上的/sbin/init, /etc/init, /bin/init和/bin/sh, 只要有一个能执行就可以。init进程会使用类exec()去调用其它进程,因而不会返回。

CPU初始化
smp_setup_processor_id()
boot_cpu_init()
setup_arch(&command_line);
setup_nr_cpu_ids()
setup_per_cpu_areas()
smp_prepare_boot_cpu()
setup_per_cpu_pageset();
calibrate_delay();
cpuset_init();
内存管理初始化
boot_init_stack_canary()
page_address_init();
mm_init_owner();
page_alloc_init();
mm_init();
rcu_init();
kmem_cache_init_late();
page_cgroup_init();
kmemleak_init();
numa_policy_init();
anon_vma_init();
page_writeback_init();
进程管理
pidhash_init();
sched_init();
sched_clock_init()
pidmap_init();
fork_init(totalram_pages);
taskstats_init_early();
文件系统
vfs_caches_init_early();
thread_info_cache_init();
vfs_caches_init(totalram_pages);
中断
early_irq_init();
init_IRQ();
softirq_init();
同步互斥
lockdep_init();
lockdep_info();
locking_selftest();
时钟
tick_init();
init_timers();
hrtimers_init();
timekeeping_init();
time_init();
调试
debug_objects_early_init();
console_init();
enable_debug_pagealloc();
debug_objects_mem_init();
dbg_late_init();
其他
sort_main_extable();
trap_init();
efi_enter_virtual_mode();
cred_init();
proc_caches_init();
buffer_init();
key_init();
security_init();
signals_init();
proc_root_init();
delayacct_init();
check_bugs();
acpi_early_init();
sfi_init_late();
未知
cgroup_init_early();
build_all_zonelists(NULL);
preempt_disable();
radix_tree_init();
prio_tree_init();
profile_init();
idr_init_cache();
cgroup_init();
ftrace_init();


 

你可能感兴趣的:(嵌入式 hi3518c内核start_kernel函数小议)