作者:严哲璟
原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
通过qemu以及gdb调试进行linux的 init/main.c内核启动代码分析
start_kernel的执行过程:首先计算机从引导区加载磁盘内容时将操作系统相关的内容加载到内存,之后操作系统开始调用start_kernel,作为初始化进程的入口
lockdep_init是检测死锁模块
然后set(init_task)即开始人工设置进程0,包括设定进程栈的起始地址,分配空间
debug_init_early初始化debug kernel相关
processor_id是指定多核CPU的ID,只有一个CPU时不做任何事情,否则返回启动时CPU的ID
boot_init_stack_canary stack_canary的防止栈溢出攻击保护的堆栈
local_irq_disable() 关闭CPU当前中断
boot_CPU_init 对于CPU核的系统来说,设置第一个CPU核为活跃
page_address_init 初始化内存页链表的地址
setup_per_cpu_areas() 每个CPU分配pre-cpu结构内存,为系统中的每个CPU的per_cpu变量申请空间
jump_label init 跳转表
trap_init 中断处理模块
mm_init 跟内存分配相关的模块
sched_init 进程调度模块
preempt_disable() 禁止内核抢占模块
build_all_zonelists() 系统内存页区(zone)链表
rest_init 创建进程1 ,并创建线程
idle进程与1号进程的切换关系:当执行了init_task之后,0号进程就启动了,rest_init的执行中有系统调用kernel_init
在之前的sche_init中,init_idle调用已经强制将init_task成为运行的进程,并成为idle进程,其代码是一个循环,这样,在sche_init之后,进程0跑起来了,而之后的rest_init产生了第一个用户进程,pid=1