本文主要是介绍Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前面粗略分析start_kernel函数,此函数中基本上是对内存管理和各子系统的数据结构初始化。在内核初始化函数start_kernel执行到最后,就是调用 rest_init函数,这个函数的主要使命就是创建并启动内核线程init。这个函数虽然意思为剩下的初始化,但是这个“剩下”的可是内容颇多,下面详细分析如下:- /*
- * 我们必须确定在一个非__init函数或
- * 其他根线程(root thread)和初始化线程(init thread)间的竞态。
- * (这种竞态可能导致start_kernel在根线程运作到cpu_idle前被free_initmem“收割”。)
- *
- *
- * gcc-3.4 偶尔会将这个函数作为内联函数, 所以使用了noinline.
- */
- static __initdata DECLARE_COMPLETION(kthreadd_done);
点击(此处)折叠或打开
- 定义一个complete变量来告诉init线程:kthreads线程已经创建完成。
- 从前似乎不是用complete锁,而是用大内核锁。
- static noinline void __init_refok rest_init(void)
- {
- int pid;
- rcu_scheduler_starting();
点击(此处)折叠或打开
- 内核RCU锁机制调度启动,因为下面就要用到
- /*
- * 我们必须先创建init内核线程,这样它就可以获得pid为1。
- * 尽管如此init线程将会挂起来等待创建kthreads线程。
- * 如果我们在创建kthreadd线程前调度它,就将会出现OOPS。
- */
- kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
点击(此处)折叠或打开
- 创建kernel_init内核线程,内核的1号进程!!!!!
- numa_default_policy();
点击(此处)折叠或打开
- 设定NUMA系统的内存访问策略为默认
- pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
-
点击(此处)折叠或打开
- 创建kthreadd内核线程,它的作用是管理和调度其它内核线程。
- 它循环运行一个叫做kthreadd的函数,该函数的作用是运行kthread_create_list全局链表中维护的内核线程。
- 调用kthread_create创建一个kthread,它会被加入到kthread_create_list 链表中;
- 被执行过的kthread会从kthread_create_list链表中删除;
- 且kthreadd会不断调用scheduler函数让出CPU。此线程不可关闭。
上面两个线程就是我们平时在Linux系统中用ps命令看到:
点击(此处)折叠或打开
- tekkaman@Super-MAGI:~/development/analyze/linux-3.0$ ps -A
- PID TTY TIME CMD
- 1 ? 00:00:00 init
- 2 ? 00:00:00 kthreadd
- ......
- kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
- rcu_read_unlock();
- complete(&kthreadd_done);
这篇关于Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!