我已经看到了各种各样的零散信息,但我似乎无法得到最终答案。你如何清理内核中的僵尸线程?
为了确保并在内核中生成处理线程的最终正确方法,我想更广泛地问这个问题。 如何在Linux内核中创建,终止和清理线程?
到目前为止我所拥有的是:
thread_func:
exited = 0;
while (!must_exit)
do stuff
exited = 1;
do_exit(0)
init_module:
must_exit = 0;
exited = 1;
kthread_run(thread_func, ...) /* creates and runs the thread */
cleanup_module:
must_exit = 1;
while (!exited)
set_current_state(TASK_INTERRUPTIBLE);
msleep(1);
/* How do I cleanup? */
我在清理解决方案中找到的最接近的是release_task,但我没有找到任何谈论它的地方。我想,由于线程函数是kthread_create
,kthread_run
等,应该有kthread_join
或kthread_wait
,但没有。do_wait
或struct task_struct *
。 do_exit
似乎也有可能,但它不需要{{1}}。
此外,我不确定{{1}}是否是一个好主意,或者是否有必要。有人可以提出一个关于如何创建,终止和清理kthread的最小草图吗?
答案 0 :(得分:15)
执行此操作的“正确”方法之一是让您的线程函数检查它是否为kthread_should_stop
,如果确实需要停止则只返回。
你不需要调用do_exit
,如果你想从模块退出函数kthread_stop
调用它,你可能不应该。{/ p>
您可以通过查看kernel/kthread.c
中的kthread_create_on_node
文档(从Linux内核3.3.1中提取)来看到这一点:
/ **
* kthread_create_on_node - 创建一个kthread * @threadfn:直到signal_pending(当前)运行的函数 * @data:@threadfn的数据ptr * @node:内存节点号。
* @namefmt:线程的printf样式名称 *
*描述:这个辅助函数创建并命名内核
*线程。该线程将被停止:使用wake_up_process()开始
*它。另见kthread_run()。
*
*如果要在特定的cpu上绑定线程,请为其节点指定 *在@node中,为kthread堆栈获取NUMA亲和力,否则给-1 *当被唤醒时,线程将以@data为其运行@threadfn() *论点。 @threadfn()可以直接调用do_exit(),如果它是
* 独立线程,没有人会调用kthread_stop()或
* 'kthread_should_stop()'为真时返回(表示
*已调用kthread_stop())。返回值应为零 *或负数错误号码;它将被传递给kthread_stop() *
*返回task_struct或ERR_PTR(-ENOMEM) * /
kthread_stop
存在“匹配”评论:
如果threadfn()可以调用do_exit()本身,调用者必须确保task_struct不会消失。
(而且我不确定你是怎么做的 - 可能会坚持使用struct_task
来get_task_struct
。)
如果你走线程创建的路径,你会得到类似的东西:
kthread_create // macro in kthread.h
-> kthread_create_on_node // in kthead.c
-> adds your thread request to kthread_create_list
-> wakes up the kthreadd_task
kthreadd_task
已在init/main.c
的{{1}}中设置。它运行reset_init
函数(来自kthreadd
)
kthread.c
kthreadd // all in kthread.c
-> create_kthread
-> kernel_thread(kthread, your_kthread_create_info, ...)
函数本身确实:
kthread
...因此,如果kthread
-> initialization stuff
-> schedule() // allows you to cancel the thread before it's actually started
-> if (!should_stop)
-> ret = your_thread_function()
-> do_exit(ret)
只是返回,则会使用其返回值调用your_thread_function
。不需要自己动手。