- Linux下有3个特殊的进程,分别是idle进程、init进程、kthreadd进程
idle进程
- idle进程(PID = 0):其前身为init_task进程,该由系统自动创建, 运行在内核态,是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。完成加载系统后,先后创建kernel_init(该进程最终演变为init进程)和kthreadd进程,并最终演变为idle进程。
-
idle进程的作用:idle进程不参与进程调度机制,当系统中没有任何进程可以调度(就绪队列为空)时,cpu就会进入该进程 —— 也就是说当系统没事干的时候就执行它,其存在的目的是为了让调度器一直处于运行状态(要不然所有的进程全挂起了调度器就会空闲下来)。
系统的空闲时间,其实就是指idle进程的”运行时间”
-
在多核系统中,每个处理器单元都有独立的一个运行队列,而每个运行队列上又有一个idle进程 —— 因此有多少cpu,就有多少idle进程。
idle进程的演化
-
Linux在无进程概念的情况下从初始化部分的代码一直执行到调用
start_kernel()
函数为止,接着创建原始进程init_task(即0号线程)。- 原始进程:虽然进程号为0,但此时还不叫idle进程,而叫init_task进程
-
原始进程init_task开始执行
start_kernel()
完成Linux内核的初始化工作(包括初始化页表,初始化中断向量表,初始化系统时间等),直到执行到start_kernel()
中的最后一个函数rest_init()
。 -
原始进程init_task在
rest_init()
中开始产生其它进程(即init进程和kthreadd进程),并最终退化为idle进程。-
rest_init()
函数的内容:static noinline void __init_refok rest_init(void) { ... kernel_thread(kernel_init, NULL, CLONE_FS); // 创建kernel_init进程(即1号进程),该进程最终演化为init进程 ... pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); // 创建kthreadd进程(即2号进程),该进程负责所有内核线程的调度和管理 ... init_idle_bootup_task(current); // 将原始进程隶属到idle调度类中 schedule_preempt_disabled(); // 使1号进程kernel_init处于运行状态 cpu_startup_entry(CPUHP_ONLINE); // 使得0号进程进入idle事件循环 —— 即最终演变为idle进程 }
-
rest_init()
函数的执行步骤:- 调用
kernel_thread()
创建1号内核进程kernel_init, 该进程随后转向用户空间, 并最终演变为init进程。 - 调用
kernel_thread()
创建kthreadd内核进程,该进程一直在内核中,并最终演变为kthreadd进程。 - 调用
init_idle_bootup_task()
将原始进程隶属到idle调度类中。 - 调用
schedule_preempt_disabled()
切换当前进程,使1号进程kernel_init处于运行状态 - 调用
cpu_startup_entry()
,而该函数又会间接调用cpu_idle_loop()
,使得0号进程进入idle事件循环 —— 即最终演变为idle进程
- 调用
-
init进程
- init进程(PID = 1):由idle通过kernel_thread创建(此时还不是init进程,而是kernel_init进程,运行在内核空间),在内核空间完成初始化后,加载init程序(该init程序会替换kernel_init进程,使得内核空间的kernel_init进程最终转换为用户空间内的1号进程init)。 该进程是系统中所有其它用户进程的祖先进程(Linux中的所有用户进程都是有init进程创建并运行的),在系统启动完成完成后,最终变为守护进程监视系统其他进程
kthreadd进程
- kthreadd(PID = 2):由idle通过kernel_thread创建,并始终运行在内核空间, 负责所有内核线程的调度和管理(它的任务就是管理和调度其他内核线程kernel_thread, 会循环执行一个kthread的函数,该函数的作用就是运行kthread_create_list全局链表中维护的kthread, 当我们调用kernel_thread创建的内核线程会被加入到此链表中,因此所有的内核线程都是直接或者间接的以kthreadd为父进程 )
http://blog.leanote.com/post/804305986@qq.com/e8672f7c86e9