上一章我们看到setup_nr_cpu_ids();
我们继续往下看:
setup_per_cpu_areas 是为了对内核的内存管理(mm)进行初始化而调用的函数之一
smp_prepare_boot_cpu();arch-specific boot-cpu钩子不知道干啥的后面可以看一下
build_all_zonelists(NULL);建立节点和内存区域之间的关系
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,
-1, -1, &unknown_bootoption);参数的解析
jump_label_init();这边是个空函数,不做处理
setup_log_buf(0);函数负责设置 printk 缓冲区
pidhash_init(); 4种PID的hash表初始化
vfs_caches_init_early(); Linux文件子系统( VFS)的初始化
sort_main_extable();Linux异常表
trap_init();主要用来处理硬件异常处理中断向量
mm_init();从bootmem迁移到伙伴系统,slab分配器也会建立。
sched_init();在启动任何中断(例如计时器中断)之前设置调度程序。完整的拓扑设置在smp_init()时完成——但同时我们仍然有一个功能正常的调度器。
preempt_disable();禁用抢占——在第一次使用cpu_idle()之前,早期的启动调度是非常脆弱的。
idr_init_cache(); idr初始化创建IDR机制的内存缓存对象。所谓的IDR就是整数标识管理机制(integerIDmanagement)。
perf_event_init(); perf是内置于Linux内核源码树中的性能剖析工具
rcu_init();RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用。
radix_tree_init(); Linux基数树(radix tree)是将指针与long整数键值相关联的机制,它存储有效率,并且可快速查询,用于指针与整数值的映射(如:IDR机制)、内存管理等。
early_irq_init();早期中断初始化
init_IRQ();初始化中断
prio_tree_init();linux中的优先搜索树的实现
init_timers();时钟系统初始化
hrtimers_init();Linux内部时钟处理机制
softirq_init();软中断初始化
timekeeping_init();Linux时间子系统
time_init();执行init_timers(), softirq_init()和time_init()函数,分别初始系统的定时器机制,软中断机制以及系统日期和时间。
profile_init();初始化-系统时间
call_function_init();
local_irq_enable();屏蔽当前CPU上的所有中断
kmem_cache_init_late();完善slab分配器的缓存机制
入侵警报!这是早期。我们在完成PCI设置等之前就启用了控制台,而console_init()必须意识到这一点。但我们确实希望尽早输出,以防出现问题。
console_init();在linux初始化过程中,除非启用了early console,否则直到console_init调用之前是没有任何输出的,它们的输出都放在__log_buf这个缓冲内的,在console_init调用时再将这个缓冲区内的数据一次性输出。
lockdep_info();Linux 死锁检测模块
当irqs启用时需要运行这个,因为它想要自我测试[硬/软]-irqs开启/关闭锁反转bug:
locking_selftest();锁定自检
page_cgroup_init();
debug_objects_mem_init();
kmemleak_init();内存泄漏检测
setup_per_cpu_pageset();前面所用per_cpu管理结构都是临时静态分配的。现在per_cpu机制已经启动,所以重新动态分配一个per_cpu管理结构并初始化。
numa_policy_init();(内存分配策略)
sched_clock_init();执行sched_clock_init之前,获取的调度时钟时间都是0,执行sched_clock_init之后,取得的调度时钟时间都是有非零值的。
calibrate_delay();函数可以计算出cpu在一秒钟内执行了多少次一个极短的循环,最终计算出来的值赋给变量loop_per_jiffs
pidmap_init();pid哈希链表
anon_vma_init();
thread_info_cache_init();thread_info就保存了特定体系结构的汇编代码段需要访问的那部分进程的数据
cred_init();任务系统初始化
fork_init(totalram_pages); 0号进程idle进程启动,这是系统唯一不通过do_fork创建的进程
proc_caches_init();构创建高速缓存内存
buffer_init();
key_init();
security_init();初始化LSM,
dbg_late_init();文件系统初始化
vfs_caches_init(totalram_pages);
signals_init();信号量相关
page_writeback_init();填充rootfs可能需要页面回写
proc_root_init();proc文件系统
cgroup_init();这个函数就是初始化cgroup所需要的参数的。cgroup最初是在2006年由google的一名工程师提出的,目的是把一些共同目标的进程放在一个组里面,而这个组里面的进程能共享指定数额的资源。而后就有了cgroup这个概念了。
cpuset_init();Cpuset子系统的实现是通过在内核代码加入一些hook代码。
taskstats_init_early();Security模块
delayacct_init();
check_bugs();
acpi_early_init(); /* before LAPIC and SMP init */在LAPIC和SMP init之前ACPI表示高级配置和电源管理接口
sfi_init_late();
ftrace_init();ftrace是Function Trace的意思,最开始主要用于记录内核函数运行轨迹;随着功能的逐渐增加,演变成一个跟踪框架。
rest_init();rest_init中调用kernel_thread函数启动了2个内核线程,分别是:kernel_init和kthreadd调用schedule函数开启了内核的调度系统,从此linux系统开始转起来了。
至此linux系统开始运行,下一张,咱们开始单个系统去分析,在linux学习中如浩瀚海洋,某一部分看不明白其实不用细究,关键是用得到的东西去学习,各种子系统,别人是如何实现的,程序的设计思想是什么。咱们下周见