通过阅读start_kernel代码,可以大致了解到内核在初始化的时候,做了以下工作:
1.lockdep_init():初始化内核依赖关系表,初始化hash表
2.boot_init_stack_canary():为栈增加保护机制,预防一些缓冲区溢出之类的攻击
3.tick_init():初始化内核时钟系统
4.boot_cpu_init():激活当前CPU
5.setup_arch():对不同体系结构的CPU设置不同的参数、选项等
6.trap_init():初始化硬件中断,函数中设置了很多中断门
7.mm_init():建立内核的内存分配器
8.sched_init():初始化任务调度
9.init_irq():中断向量的初始化,很多初始化工作。
10.rest_init():剩下的初始化工作,这里面其实做了很多工作
其中几个重要的步骤跟踪:
1.set_task_stack_end_magic(&init_task);
在该函数中初始化了系统第一个task_struct结构体,主要社设置了该任务的堆栈。
2.trap_init()函数
3.调用 rest_init()函数进行最后的初始化工作,包括创建1号进程(init),第一个内核线程等操作
Linux一开始先在无进程的情况下将一直从初始化部分的代码执行到start_kernel,然后再到其最后一个函数调用rest_init。从rest_init开始,Linux开始产生进程,在rest_init中,通过init_task产生pid=0的进程,即0号进程(idle进程),它是内核状态下的进程;在rest_init函数中,内核通过kernel_ini创建1号进程,它是第一个用户态进程。关于init_task(也就是idle),当运行队列中没有别的就绪进程时,init_task(也就是idle)将会被调用,它的核心是一个while(1)循环,在循环中它将会调用schedule函数以便在运行队列中有新进程加入时切换到该新进程上。