如何使用 kthreads 正确实现完成?

How do I properly implement completions with kthreads?

我正在尝试编写一个在 kthreads 上实现完成的内核模块。

我尝试编写的逻辑是:父 foo() 将创建一个 kthread bar()foo() 将调用 wait_for_completion() 并等待线程 bar() 完成。 bar() 将执行其主体,然后在 return() 之前调用 complete()。父级 foo() 继续其其余代码直至完成。

这是代码的摘录:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/completion.h>
#include <linux/kthread.h>
#include <net/tcp.h>

//A couple of standard descriptions
MODULE_LICENSE("GPL");

//Struct used to pass kthread args
typedef struct {
    int side;       //Specify motor side
    int direction;      //Specify motor rotation direction
    struct completion wait_for_motor;   //completion struct
} kthread_arg;

//kthread struct declaration
static struct task_struct *left_motor;

static int motor_rotate(void* data) {
    //Cast and dereference argument structure
    kthread_arg in = *(kthread_arg*)data;

    int i = in.side;
    printk(KERN_NOTICE "Module: motor side=%d\n",i);
    printk(KERN_NOTICE "Module: Completing kthread...\n");

    //Signal completion
    complete(&(in.wait_for_motor));

    printk(KERN_NOTICE "Module: Kthread Completed.\n"); 

    return 0;
}

//Init function
static int main_init(void)
{
    /*  Body of code */

    //Initialize argument structures;
    static kthread_arg kta_left_motor;

    //Set motor side
    kta_left_motor.side = 0;

    //Initialize completion
    init_completion(&kta_left_motor.wait_for_motor);

    //Create and run kthread
    left_motor = kthread_run(&motor_rotate, (void*)&kta_left_motor, "motor_rotate_0");

    printk(KERN_NOTICE "Module: Wait_for_completion...\n");

    //Put function to sleep until kthread signals completion
    wait_for_completion(&(kta_left_motor.wait_for_motor));

    printk(KERN_NOTICE "Module: Completion done.\n");

    /*  More function calls and code    */

    return 0;
}

//Exit function
static void leave_exit(void)
{
    printk(KERN_INFO "Exit module.\n");
}

module_init(main_init);
module_exit(leave_exit);

这里是 kern.log 输出:

Module: Wait_for_completion...
Module: motor side=0
Module: Completing kthread...
Module Kthread Completed.

请注意,父函数永远不会被唤醒,我们也永远不会到达 printk(KERN_NOTICE "Module: Completion done.\n"); 行。当我 运行 此代码时,模块只是挂起。

我已经从头到尾阅读了 completions document 大约 100 遍,我尝试使用 complete_all(),检查 done 的值(总是输出 0),使用 completion_done()try_wait_for_completion() 没有成功。

我不知道是否有更好的方法来实现上述目标。

如果我完全删除完成实现,我发现父函数 foo() 总是在 之前 所有 kthreads 开始 运行ning 之前执行完成,而我只需要 foo() 到 运行 after all kthreads 执行完毕。

Ubuntu

uname -r: 4.10.0-42-generic

修改motor_rotate()如下图:

  1. kthread_arg *in = (kthread_arg *) data;
  2. int i = in->side;
  3. complete(&(in->wait_for_motor));