如何正确实现kthreads的完成?

时间:2018-01-06 20:14:49

标签: c linux-kernel linux-device-driver kernel-module

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

我尝试编写的逻辑是:父foo()将创建一个kthread bar()foo()将调用wait_for_completion()并等待线程bar()完成。 bar()将执行其正文,然后在complete()之前调用return()。父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检查completion_done()的值(始终输出0)并且try_wait_for_completion()没有成功。

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

如果我完全删除了完成实现,我发现父函数foo()始终执行,然后所有kthreads开始运行,而我需要的是foo()所有 kthreads执行完毕后仅运行

Ubuntu的

uname -r: 4.10.0-42-generic

1 个答案:

答案 0 :(得分:3)

修改motor_rotate(),如下所示:

  1. kthread_arg * in =(kthread_arg *)data;
  2. int i = in-&gt; side;
  3. 完成(及(IN-&GT; wait_for_motor));