在内核中处理线程的正确方法?

我已经看到了各种各样的零散信息,但我似乎无法得到最终答案。 你如何清理内核中的僵尸线程?

为了确保并在内核中生成处理线程的最终正确方法,我想更广泛地问这个问题。 如何在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_createkthread_run等,应该有一个kthread_joinkthread_wait ,但是没有。 do_wait似乎也有可能,但它不需要struct task_struct *

此外,我不确定do_exit是否是一个好主意,或者是否有必要。 有人可以提出如何创建,终止和清理kthread的最小草图吗?

执行此操作的“正确”方法之一是让您的线程函数检查它是否为kthread_should_stop ,如果确实需要停止则返回。

你不需要调用do_exit ,如果你打算从模块退出函数kthread_stop它,你可能不应该。

您可以通过查看kernel/kthread.c kthread_create_on_node文档来看到这kernel/kthread.c (从Linux内核3.3.1中提取):

/ **
* kthread_create_on_node – 创建一个kthread。
* @threadfn:运行到signal_pending(当前)的函数。
* @data:@streadfn的数据ptr。
* @node:内存节点号。
* @namefmt:线程的printf样式名称。
*
*描述:这个辅助函数创建并命名内核
*线程。 该线程将被停止:使用wake_up_process()启动
*它。 另请参见kthread_run()。
*
*如果要在特定的cpu上绑定线程,请给它的节点
*在@node中,为kthread堆栈获取NUMA亲和力,否则给-1。
*当被唤醒时,线程将以@data为运行@threadfn()
*论点。 @threadfn()可以直接调用do_exit(),如果它是a
* 独立线程,没有人会调用kthread_stop(),或
* ‘kthread_should_stop()’为真时返回 (表示
*已调用kthread_stop())。 返回值应为零
*或负数错误号码; 它将被传递给kthread_stop()。
*
*返回task_struct或ERR_PTR(-ENOMEM)。
* /

kthread_stop存在“匹配”注释:

如果threadfn()可以调用do_exit()本身, 则调用者必须确保task_struct不会消失

(而且我不确定你是怎么做的 – 可能用get_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_taskreset_init init/main.creset_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只返回, do_exit使用其返回值调用do_exit 。 不需要自己动手。