diff --git a/study/kernel/01-process/02-create/07-kernel_thead/README.md b/study/kernel/01-process/02-create/07-kernel_thead/README.md index 9c06549..0877be4 100644 --- a/study/kernel/01-process/02-create/07-kernel_thead/README.md +++ b/study/kernel/01-process/02-create/07-kernel_thead/README.md @@ -109,8 +109,6 @@ struct task_struct 使用kthread_run,与kthread_create不同的是,其创建新线程后立即唤醒它,其本质就是先用kthread_create创建一个内核线程,然后通过wake_up_process唤醒它 -内核线程会出现在系统进程列表中, 但是在ps的输出中进程名command由方括号包围, 以便与普通进程区分。 - ##2号进程kthreadd的诞生 ------- @@ -145,6 +143,17 @@ Linux中的workqueue机制就是为了简化内核线程的创建。通过kthrea + +内核线程会出现在系统进程列表中, 但是在ps的输出中进程名command由方括号包围, 以便与普通进程区分。 + +如下图所示, 我们可以看到系统中, 所有内核线程都用[]标识, 而且这些进程父进程id均是2, 而2号进程kthreadd的父进程是0号进程 + +>使用ps -eo pid,ppid,command + +![ps查看内核线程](./images/ps-eo.jpg) + + + ##kernel_thread ------- @@ -208,12 +217,22 @@ extern void daemonize(void); 延后内核的创建工作, 将内核线程的创建工作交给一个内核线程来做, 即kthreadd 2号进程 -但是在kthreadd还没创建之前, 我们只能通过kernel_thread这种方式去创建, +但是在kthreadd还没创建之前, 我们只能通过kernel_thread这种方式去创建 +同时kernel_thread的实现也改为由_do_fork(早期内核中是do_fork)来实现, 参见[kernel/fork.c](http://lxr.free-electrons.com/source/kernel/fork.c?v=4.5#L1779) +` +``c +pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + return _do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn, + (unsigned long)arg, NULL, NULL, 0); +} +``` ##kthread_create ------- + ```c struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), void *data, @@ -253,3 +272,39 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), 使用kthread_run,与kthread_create不同的是,其创建新线程后立即唤醒它,其本质就是先用kthread_create创建一个内核线程,然后通过wake_up_process唤醒它 + +#内核线程的退出 +------- + +线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。 + +```c + int kthread_stop(struct task_struct *thread); +``` + +kthread_stop() 通过发送信号给线程。 + +如果线程函数正在处理一个非常重要的任务,它不会被中断的。当然如果线程函数永远不返回并且不检查信号,它将永远都不会停止。 + +在执行kthread_stop的时候,目标线程必须没有退出,否则会Oops。原因很容易理解,当目标线程退出的时候,其对应的task结构也变得无效,kthread_stop引用该无效task结构就会出错。 + +为了避免这种情况,需要确保线程没有退出,其方法如代码中所示: +```c +thread_func() +{ + // do your work here + // wait to exit + while(!thread_could_stop()) + { + wait(); + } +} + +exit_code() +{ + kthread_stop(_task); //发信号给task,通知其可以退出了 +} +``` + +这种退出机制很温和,一切尽在thread_func()的掌控之中,线程在退出时可以从容地释放资源,而不是莫名其妙地被人“暗杀”。 + diff --git a/study/kernel/01-process/02-create/07-kernel_thead/images/ps-eo.jpg b/study/kernel/01-process/02-create/07-kernel_thead/images/ps-eo.jpg new file mode 100644 index 0000000..7524ef6 Binary files /dev/null and b/study/kernel/01-process/02-create/07-kernel_thead/images/ps-eo.jpg differ