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

时间:2012-04-16 16:03:13

标签: c multithreading linux-kernel zombie-process

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

为了确保并在内核中生成处理线程的最终正确方法,我想更广泛地问这个问题。 如何在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_waitstruct task_struct *do_exit似乎也有可能,但它不需要{{1}}。

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

1 个答案:

答案 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_taskget_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。不需要自己动手。