我们可以在内核中创建很多线程了,但是这些线程之间怎么互动呢?
完成量机制,是linux系统提供的一种同步机制,用于一个执行单元等待另一个执行单元执行完某件事。(一个线程阻塞在那,等待另外一个线程去唤醒它)
struct completion{
unsigned int done;
wait_queue_head_t wait;
};
1、定义completion
struct completion my_completion;
2、初始化completion
init_completion(&my_completion);
3、等待completion
void wait_for_completion(struct completion *c);
void wait_for_completion_interruptible(struct completion *c);
void wait_for_completion_killable(struct completion *c);
unsigned long wait_for_completion_timeout(struct completion *c);
4、唤醒completion
void complete(strutc completion *c); //唤醒一个等待的执行单元
void complete_all(strutc completion *c); //唤醒全部的等待执行单元
下面用一个列子说明一个线程换新另外一个线程的用法:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/completion.h>
MODULE_LICENSE("Dual BSD/GPL");
static struct task_struct *tsk_1;
static struct task_struct *tsk_2;
static struct completion wakeup;
static int wakeup_thread(void *data)
{
int wakeup_time_count = 0;
do {
printk(KERN_INFO "wakeup_thread : %d times", ++wakeup_time_count);
msleep(1000);
if(wakeup_time_count == 10){
/* wakeup completion */
complete(&wakeup);
}
}while(!kthread_should_stop());
return wakeup_time_count;
}
static int completion_test_thread(void *data)
{
int completion_time_count = 0;
/* wait wakeup_thread completion */
wait_for_completion(&wakeup);
do{
printk(KERN_INFO "completion_test_thread : %d times", ++completion_time_count);
msleep(1000);
}while(!kthread_should_stop());
return completion_time_count;
}
static int kai_init(void)
{
printk(KERN_INFO "completion test init!\n");
/* init completion */
init_completion(&wakeup);
/* create wakeup_thread thread */
tsk_1 = kthread_run(wakeup_thread,NULL,"wakeup_thread");
if(IS_ERR(tsk_1)){
printk(KERN_INFO "create wakeup_thread failed!\n");
return 1;
}
/* create completion_test_thread thread */
tsk_2 = kthread_run(completion_test_thread,NULL,"completion_test_thread");
if(IS_ERR(tsk_2)){
printk(KERN_INFO "create completion_test_thread thread failed!\n");
return 1;
}
return 0;
}
static void kai_exit(void)
{
printk(KERN_INFO "completion test exit!\n");
/*complete_all(&wakeup);*/
if (!IS_ERR(tsk_2)){
int ret_2 = kthread_stop(tsk_2);
printk(KERN_INFO "completion_test_thread function has run %ds\n", ret_2);
}
if (!IS_ERR(tsk_1)){
int ret_1 = kthread_stop(tsk_1);
printk(KERN_INFO "wakeup_thread function has run %ds\n", ret_1);
}
}
module_init(kai_init);
module_exit(kai_exit);
上面这个例子中 我们在kai_init中初始化了一个completion,并且创建了两个线程:wakeup_thread、completion_test_thread,
在completion_test_thread线程中我们调用了wait_for_completion 来将其阻塞住,及需要等待其他线程来唤醒该线程,在wakeup_thread线程中我们设置了每秒打印一个消息,并在第十秒的时候去唤醒completion_test_thread 中阻塞的completion
。
编译执行我们通过打印信息可以看到:
在completion_test_thread 线程未被唤醒前只能看到wakeup_thread线程的打印信息。此时completion_test_thread 线程被阻塞,而当wakeup_thread线程 调用了complete 唤醒了completion后,两个线程都可以由打印输出。
我们可以认为在wakeup_thread线程 中唤醒completion和completion_test_thread 线程被唤醒completion 是同步的。