内核线程what? 内核本身启动的线程,也被称之为内核守护进程
内核线程分为两种类型
- 启动后一直等待,直到内核请求线程执行某一动作
- 启动后周期运行,检测特定资源的使用,在用量超出时采取行动
kernel_thread 启动一个内核线程,特定于体系结构,但是原型相同
asm-arm/process.h
1 /* 2 * Create a new kernel thread 3 */ 4 extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
fn回调函数
arg 参数
flag 可以指定CLONE 参数
kernel_thread第一个任务时构建一个pt_regs实例,并对其中的寄存器赋值,这与普通fork类似,接下来就是熟悉的do_fork
p = do_fork( flags| CLONE_VM| CLONE_UNTRACED,0,®s, 0,null,null )
内核线程有两个特别之处
- 在CPU的管态执行,而不是用户态
- 只可以访问虚拟地址空间的内核部分,不能访问用户空间
task_struct 包含两个mm_structs指针
sched.h
1 struct task_struct { 2 ... 3 struct mm_struct *mm, *active_mm; 4 ... 5 6 }
大多数系统虚拟地址分为两个部分,底部用户层访问,上部供内核使用
内核代表用户层程序运行时(比如系统调用),虚拟地址空间的用户部分由mm指向的mm_struct描述
lazy TLB (没太看懂,后面补上。。。)
内核线程的实现方法:
1 古老的方法,将一个函数直接传递给kernel_thread,该函数负责调用daemonize以转换为守护进程,会依次引发下列操作
-
- 该函数从内核释放其父进程(用户进程)的所有资源。
- daemonize阻塞信号接收
- 将init用作守护进程的父进程
2 kthread_create
kernel/kthread.c
1 /** 2 * kthread_create - create a kthread. 3 * @threadfn: the function to run until signal_pending(current). 4 * @data: data ptr for @threadfn. 5 * @namefmt: printf-style name for the thread. 6 * 7 * Description: This helper function creates and names a kernel 8 * thread. The thread will be stopped: use wake_up_process() to start 9 * it. See also kthread_run(), kthread_create_on_cpu(). 10 * 11 * When woken, the thread will run @threadfn() with @data as its 12 * argument. @threadfn() can either call do_exit() directly if it is a 13 * standalone thread for which noone will call kthread_stop(), or 14 * return when 'kthread_should_stop()' is true (which means 15 * kthread_stop() has been called). The return value should be zero 16 * or a negative error number; it will be passed to kthread_stop(). 17 * 18 * Returns a task_struct or ERR_PTR(-ENOMEM). 19 */ 20 struct task_struct *kthread_create(int (*threadfn)(void *data), 21 void *data, 22 const char namefmt[], 23 ...)
该函数创建一个新的内核线程,名字有namefmt指出,线程最初是停止的,需要调用wake_up_process启动
3 kthread_run 参数与kthread_create相同,它调用kthread_create创建新的线程,但是立即唤醒它
还可以使用kthread_create_cpu代替kthread_create
内核线程在PS输出中用方括号加以区别