18

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

为了确保并产生处理内核线程的最终正确方法,我想更广泛地提出这个问题。如何在 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_joinor kthread_wait,但没有。do_wait似乎也有可能,但不需要struct task_struct *.

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

4

1 回答 1

19

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

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

您可以通过查看kthread_create_on_nodein的文档来了解这一点kernel/kthread.c(从 Linux 内核 3.3.1 中提取):

/**
* kthread_create_on_node - 创建一个 kthread。
* @threadfn:在 signal_pending(current) 之前运行的函数。
* @data:@threadfn 的数据指针。
* @node:内存节点号。
* @namefmt:线程的 printf 样式名称。
*
* 描述:此辅助函数创建并命名内核
* 线程。线程将被停止:使用 wake_up_process() 来启动
它。另请参见 kthread_run()。
*
* 如果线程要绑定在特定的 cpu 上,
则在 @node 中给它的节点 *,以获得 kthread 堆栈的 NUMA 亲和性,否则给 -1。
* 当被唤醒时,线程将运行 @threadfn() 并使用 @data 作为它的
* 参数。@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.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将以其返回值调用。不需要自己做。

于 2012-04-16T16:59:36.900 回答