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

Sha*_*baz 15 c multithreading zombie-process linux-kernel

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

为了确保并在内核中生成处理线程的最终正确方法,我想更广泛地提出这个问题.如何在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? */
Run Code Online (Sandbox Code Playgroud)

我发现清理解决方案最接近的是release_task,但我没有找到任何关于它的讨论.我想象,因为线程功能kthread_create,kthread_run等等,应该有一个kthread_joinkthread_wait,但是没有.do_wait似乎也有可能,但它不需要struct task_struct *.

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

Mat*_*Mat 16

执行此操作的"正确"方法之一是让您的线程函数检查它是否正确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(当前)的函数.
*@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用a 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
Run Code Online (Sandbox Code Playgroud)

kthreadd_task设置init/main.creset_init.它运行kthreadd功能(从kthread.c)

kthreadd                                                 // all in kthread.c
  -> create_kthread
    -> kernel_thread(kthread, your_kthread_create_info, ...)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

...因此,如果your_thread_function简单地返回,do_exit将使用其返回值进行调用.不需要自己动手.