内核线程是直接由内核本身启动的进程。内核线程实际上是将内核函数委托给独立的进程,与系统中其他进程“并行”执行(实际上,也并行于内核自身的执行),内核线程经常被称为内核“守护进程”。它们主要用于执行下列任务:
l 周期性地将修改的内存页与页来源块设备同步。
l 如果内存页很少使用,则写入交换区。
l 管理延时动作
l 实现文件系统的事务日志。
内核线程主要有两种类型:
1. 线程启动后一直等待,直至内核请求线程执行某一特定操作。
2. 线程启动后按周期性间隔运行,检测特定资源的使用,在用量超出或低于预置的限制时采取行动。
内核线程由内核自身生成,其特点在于:
1. 它们在CPU的管态执行,而不是用户态。
2. 它们只可以访问虚拟地址空间的内核部分(高于TASK_SIZE的所有地址),但不能访问用户空间。
task_struct进程描述符中包含两个跟进程地址空间相关的字段mm, active_mm,对于普通用户进程来说,mm指向虚拟地址空间的用户空间部分,而对于内核线程,mm为NULL。
active_mm主要用于优化,由于内核线程不与任何特定的用户层进程相关,内核并不需要倒换虚拟地址空间的用户层部分,保留旧设置即可。由于内核线程之前可能是任何用户层进程在执行,故用户空间部分的内容本质上是随机的,内核线程决不能修改其内容,故将mm设置为NULL,同时如果切换出去的是用户进程,内核将原来进程的mm存放在新内核线程的active_mm中。假如内核线程之后运行的进程与之前是同一个,内核并不需要修改用户空间地址表,TLB中 信息仍然有效;只有在内核线程之后执行的进程与此前用户层进程不同时,才需要切换,并清除对应TLB数据。
内核线程可以通过两种方式实现:
1. 将一个函数传递给kernel_thread,该函数接下来负责帮助内核调用daemonize已转换为守护进程,具体包括下列操作:
l 该函数释放其父进程的所有资源,不然这些资源会一直锁定直到线程结束。
l 阻塞信号的接收。
l 将init用作守护进程的父进程。
2. 创建内核更常用的方法是辅助函数kthread_create,该函数创建一个新的内核线程。最初线程是停止的,需要使用wake_up_process启动它。或使用kthread_run,与kthread_create不同的是,其创建新线程后立即唤醒它。
通过ps fax命令查看系统中运行的内核线程信息。