我正在尝试编写一个在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
答案 0 :(得分:3)
修改motor_rotate(),如下所示: