繁体   English   中英

使用“return”或“do_exit()”终止内核线程是一个好习惯吗?

[英]Is it a good practice to terminate kernel thread with “return” or “do_exit()”?

我的目标是仅从我的驱动程序的探测功能执行内核线程,执行固件下载。

为简单起见,提供示例代码(非实际代码)

#include<linux/module.h>
#include<linux/init.h>
#include<linux/kthread.h>

MODULE_LICENSE("GPL");

struct task_struct *kthread;


static int thread_func(void* data)
{
    printk("In %s function\n", __func__);
    return 0;
}

static int hello_init(void)
{
    int ret = 0;

    printk("Hello World\n");
    kthread = kthread_run(thread_func,
            NULL, "kthread-test");
    if (IS_ERR(kthread)) {
        ret = PTR_ERR(kthread);
        printk("Unable to run kthread err %d\n", ret);
        return ret;
    }
    return 0;
}


static void hello_exit(void)
{
    printk("Bye World\n");

}

我没有使用以下任何一种,因为:

  1. kthread_should_stop() - 用于我不想要的连续执行
  2. kthread_stop(struct task_struct *thread) - 如果包含在模块退出函数中,则导致内核崩溃,因为线程在执行一次后已经终止

这是正确的方法吗? 如果没有请建议

在模块退出函数返回之前,您需要确保线程已经消失。 一种方法是使用“完成”结构。

基本思想是在启动线程之前初始化完成结构,使线程在完成时将完成结构标记为“完成”,并使模块退出函数(或其他)等待完成结构标记为完成。

  1. 先决条件

     #include <linux/completion.h> 
  2. 初始化完成结构

    如果静态分配完成结构变量,则可以使用DECLARE_COMPLETION宏在变量定义中初始化它:

     static DECLARE_COMPLETION(thread_done); 

    (当完成结构变量在堆栈上时,还有一个DECLARE_COMPLETION_ONSTACK宏。)

    或者,可以定义未初始化的struct completion (例如,作为动态分配的结构的成员),然后通过调用init_completion(...)初始化:

     struct completion thread_done; ... init_completion(&thread_done); 
  3. 创建线程

     kthread = kthread_run(thread_func, NULL, "kthread-test"); if (IS_ERR(kthread)) { complete(&thread_done); /* <-- may or may not be required */ ret = PTR_ERR(kthread); return ret; } 

    在上面,如果kthread_run(...)失败,则在某些代码稍后等待完成的情况下,将完成结构标记为“完成”。 如果保证以后没有任何东西等待完成,则complete(&thread_done); 呼叫可以省略。

  4. 退出线程

    线程应调用complete_and_exit(...)将线程标记为“完成”,而不是从线程函数返回或调用do_exit(...)

     complete_and_exit(&thread_done, 0); 

    调用complete_and_exit(...)complete(...)do_exit(...)单独调用更安全。 通过单独调用complete(...)do_exit(...)有可能在complete(...)返回时已经卸载了模块代码,因此线程可以执行不存在的或随机的代码。 调用complete_and_exit(...)可以避免发生这种情况,因为函数存在于模块代码之外并且永远不会返回。

  5. 确保线程已完成

    要确保线程已完成,请调用wait_for_completion(...)

     wait_for_completion(&thread_done); 

    返回时,线程已经退出或者仍然在调用complete_and_exit(...)仍在运行,并且即将退出。 在任何一种情况下,它都不再运行任何模块代码,因此可以安全地继续。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM