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(),如下所示:
- kthread_arg *in = (kthread_arg *) data;
- int i = in->side;
- complete(&(in->wait_for_motor));
kthread_arg * in =(kthread_arg *)数据;
int i = in-> side;
#1
3
Modify motor_rotate() as shown below:
修改motor_rotate(),如下所示:
- kthread_arg *in = (kthread_arg *) data;
- int i = in->side;
- complete(&(in->wait_for_motor));
kthread_arg * in =(kthread_arg *)数据;
int i = in-> side;