一. 前言
前文分析到Linux内核正式启动,完成了实模式到保护模式的切换,并做好了各种准备工作。下来就
要看开始内核初始化工作了,源码位置位于init/main.c中的start_kernel(),源码如附录所示。这包括了
一系列重要的初始化工作,本文会介绍其中一部分较为重要的,但是详细的介绍依然会留在后文各个模
块的源码学习中单独进行。本文的目的在于承接上文给出一个从内核启动到各个模块开始运转的过程介
绍,而不是详细的各部分内容介绍。
创建0号进程:INIT_TASK(init_task)
异常处理类中断服务程序挂接:trap_init()
内存初始化:mm_init()
调度器初始化sched_init()
剩余初始化:rest_init()
二. 0号进程的创建
start_kernel()上来就会运行 set_task_stack_end_magic(&init_task)创建初始进程。init_task的定义
是 struct task_struct init_task = INIT_TASK(init_task)。它是系统创建的第一个进程,我们称为 0 号进
程。这是唯一一个没有通过 fork 或者 kernel_thread产生的进程,是进程列表的第一个。
如下所示为init_task的定义,这里只节选了部分,采用了gcc的结构体初始化方式为其进行了直接赋
值生成。
/*
* Set up the first task table, touch at your own risk!. Base=0,
* limit=0x1fffff (=2MB)
*/
struct task_struct init_task
#ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK
__init_task_data
#endif
= {
......
.state = 0,
.stack = init_stack,
.usage = REFCOUNT_INIT(2),
.flags = PF_KTHREAD,
.prio = MAX_PRIO - 20,
.static_prio = MAX_PRIO - 20,
.normal_prio = MAX_PRIO - 20,
.policy = SCHED_NORMAL,
.cpus_ptr = &init_task.cpus_mask,
.cpus_mask = CPU_MASK_ALL,
.nr_cpus_allowed = NR_CPUS,
.mm = NULL,
.active_mm = &init_mm,
......
.thread_pid = &init_struct_pid,
.thread_group = LIST_HEAD_INIT(init_task.thread_group),
.thread_node = LIST_HEAD_INIT(init_signals.thread_head),
......
};