Linux内核线程与用户线程
2018-02-08

内核线程与用户线程、用户进程

相同点是:
都由do_fork()创建,每个线程都有独立的task_struct和内核栈;
都参与调度,内核线程也有优先级,会被调度器平等地换入换出。

不同之处在于:
内核线程只工作在内核态中;而用户线程则既可以运行在内核态(执行系统调用时),也可以运行在用户态;
内核线程没有用户空间,所以对于一个内核线程来说,它的0-3G的内存空间是空白的,它的current->mm是空的,与内核使用同一张页表;而用户线程则可以看到完整的0-4G内存空间。

内核线程的创建和作用

创建

在Linux内核启动的最后阶段,系统会创建两个内核线程,一个是init,一个是kthreadd。其中init线程的作用是运行文件系统上的一系列”init”脚本,并启动shell进程,所以init线程称得上是系统中所有用户进程的祖先,它的pid是1。kthreadd线程是内核的守护线程,在内核正常工作时,它永远不退出,是一个死循环,它的pid是2。

作用

内核线程的作用主要有:

1周期性的将dirty内存页同步到磁盘设备上。 比如 bpflush线程周期性的把dirty数据写回磁盘
2内存页很少的情况下,把内存page 交换到磁盘空间。 比如kswapd,系统会为每一个NUMA创建一个kswapd进程,但是在非NUMA系统上,则仅有一个kswapd
3管理延时动作
4实现文件系统的事物日志

主要包括两种类型的内核线程:

线程按周期性间隔运行,检测特定资源的使用,在用量超出或者低于预置的限制时采取行动在线程启动后则一直等待,直到内核线程请求执行某一特定的操作。

总结

通过上述不同之处的对比可以发现,内核线程没有用户内存空间,与之相对的是用户进程(注意,此处不是用户线程),用户进程同时具备内核空间与用户空间,在进行系统调用时用户进程会由用户内存空间陷入内核内存空间。之所以此处采用内核线程与用户进程(而非用户线程)进行对比,是由于内核线程(kernel thread)是“独立运行在内核空间的标准进程”(以上这句话摘自《linux内核设计与实现》),因此从功能上看内核线程一方面具有进程的概念特点——具有独立功能的程序关于某个数据集合上的一次执行活动,是系统进行资源分配的单位,同时内核线程又具有线程的概念特点——进程内的一个可调度实体。