Linux内核初始化步骤(三)

在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();
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40788950/article/details/84558246