在start_kernl函数的最后调用了reset_init函数进行后续的初始化
static noinline void __init_refok rest_init(void)
{
int pid;
rcu_scheduler_starting();//内核RCU锁机制调度启动
/*
* We need to spawn init first so that it obtains pid 1, however
* the init task will end up wanting to create kthreads, which, if
* we schedule it before we create kthreadd, will OOPS.
*/
/*我们必须先创建init进程以便于使它获得进程号1,然而init进程将会被挂起来等待创建kthreads
线程,如果我们在创建kthreadd线程前调度它,将会导致OOPS错误*/
/*rest_init()函数最主要的历史使命就是启动内核线程kernel_init*/
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
numa_default_policy();
/*启动内核线程kthreadd,运行kthread_create_list全局链表中的kthread
1.它循环运行一个叫做kthreadd的函数,该函数的作用是运行ktheard_create_list全局链表中
维护的内核线程;
2.调用kthread_create创建一个kthread,它会被加入到kthread_create_list链表中;
3.被执行过的kthread会从kthread_create_list链表中删除
4.且kthreadd会不断调用scheduler函数让出CPU,此线程不可关闭
上面两个线程就是我们平时在Linux系统中用ps命令看到:
*/
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
rcu_read_lock();
kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
rcu_read_unlock();
complete(&kthreadd_done);
/*1.获取kthreadd的线程信息,获取完成说明kthreaddd已经创建成功。并通过一个complete
变量(kthreadd_done)来通知kernel_init线程*/
/*
* The boot idle thread must execute schedule()
* at least once to get things moving:
*/
init_idle_bootup_task(current);
preempt_enable_no_resched();
schedule();
/* Call into cpu_idle with preempt disabled */
preempt_disable();
cpu_idle();
}