如何使用 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()
如下图:
kthread_arg *in = (kthread_arg *) data;
int i = in->side;
complete(&(in->wait_for_motor));
我正在尝试编写一个在 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()
如下图:
kthread_arg *in = (kthread_arg *) data;
int i = in->side;
complete(&(in->wait_for_motor));