如何正确实现kthreads的完成?

时间:2022-04-15 00:47:16

I am attempting to write a kernel module that implements completions on kthreads.

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

The logic I am trying to code is: parent foo() will create a kthread bar(). foo() will call wait_for_completion() and wait for the thread bar() to finish. bar() will execute its body and then call complete() right before return(). Parent foo() continue the rest of its code to completion.

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

Here is an extract of the code:

以下是代码的摘录:

#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);

Here is the kern.log output:

这是kern.log输出:

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

Notice that the the parent function is never awakened and we never get to the line printk(KERN_NOTICE "Module: Completion done.\n");. When I run this code the module simply hangs.

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

I have read the completions document top to bottom about 100 times, I have attempted using complete_all(), checking the value of done (always outputs 0), using completion_done() and try_wait_for_completion() to no success.

我已经从上到下阅读了完成文档大约100次,我尝试使用complete_all(),检查done的值(总是输出0),使用completion_done()和try_wait_for_completion()没有成功。

I don't know if there is a better way to go about achieving the goal explained above.

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

If I remove the completions implementation entirely I find that the parent function foo() is always executed to completion before all kthreads start running, whereas what I need is for foo() to run only after all kthreads are done executing.

如果我删除的完成实现完全我发现父母函数foo()一直执行到完成所有kthreads开始运行前,而我需要的是foo的()给所有kthreads完成执行后才能运行。

Ubuntu

uname -r: 4.10.0-42-generic

uname -r:4.10.0-42-generic

1 个解决方案

#1


3  

Modify motor_rotate() as shown below:

修改motor_rotate(),如下所示:

  1. kthread_arg *in = (kthread_arg *) data;
  2. kthread_arg * in =(kthread_arg *)数据;

  3. int i = in->side;
  4. int i = in-> side;

  5. complete(&(in->wait_for_motor));

#1


3  

Modify motor_rotate() as shown below:

修改motor_rotate(),如下所示:

  1. kthread_arg *in = (kthread_arg *) data;
  2. kthread_arg * in =(kthread_arg *)数据;

  3. int i = in->side;
  4. int i = in-> side;

  5. complete(&(in->wait_for_motor));