接上 一篇文章 ,這里介紹另一種線程間通信的方式:completion機制。Completion機制是線程間通信的一種輕量級機制:允許一個線程告訴另一個線程工作已經完成。為使用 completion, 需要包含頭文件 <linux/completion.h>。
可以通過以下方式來創建一個 completion :
DECLARE_COMPLETION(my_completion);
或者, 動態創建和初始化:
struct completion my_completion;
init_completion(&my_completion);
等待 completion 是一個簡單事來調用: void wait_for_completion(struct completion *c);
注意:這個函數進行一個不可打斷的等待. 如果你的代碼調用 wait_for_completion 並且
沒有人完成這個任務, 結果會是一個不可殺死的進程。
completion 事件可能通過調用下列之一來發出:
void complete(struct completion *c);
void complete_all(struct completion *c);
如果多於一個線程在等待同一個 completion 事件, 這 2 個函數做法不同. complete 只
喚醒一個等待的線程, 而 complete_all 允許它們所有都繼續。
下面來看使用completion機制的實現代碼:
#include <linux/init.h> #include <linux/module.h> #include <linux/kthread.h> #include <linux/wait.h> #include <linux/completion.h> MODULE_LICENSE("Dual BSD/GPL"); static struct completion comp; static struct task_struct * _tsk; static struct task_struct * _tsk1; static int tc = 0; static int thread_function(void *data) { do { printk(KERN_INFO "IN thread_function thread_function: %d times \n", tc); wait_for_completion(&comp); //tc = 0; ///在哪里都行 printk(KERN_INFO "has been woke up !\n"); }while(!kthread_should_stop()); return tc; } static int thread_function_1(void *data) { do { printk(KERN_INFO "IN thread_function_1 thread_function: %d times\n", ++tc); if(tc == 10) { complete(&comp); tc = 0; } msleep_interruptible(1000); }while(!kthread_should_stop()); return tc; } static int hello_init(void) { printk(KERN_INFO "Hello, world!\n"); init_completion(&comp); _tsk = kthread_run(thread_function, NULL, "mythread"); if (IS_ERR(_tsk)) { printk(KERN_INFO "first create kthread failed!\n"); } else { printk(KERN_INFO "first create ktrhead ok!\n"); } _tsk1 = kthread_run(thread_function_1,NULL, "mythread2"); if (IS_ERR(_tsk1)) { printk(KERN_INFO "second create kthread failed!\n"); } else { printk(KERN_INFO "second create ktrhead ok!\n"); } return 0; } static void hello_exit(void) { printk(KERN_INFO "Hello, exit!\n"); if (!IS_ERR(_tsk)){ int ret = kthread_stop(_tsk); printk(KERN_INFO "First thread function has stopped ,return %d\n", ret); } if(!IS_ERR(_tsk1)) { int ret = kthread_stop(_tsk1); printk(KERN_INFO "Second thread function_1 has stopped ,return %d\n",ret); } } module_init(hello_init); module_exit(hello_exit);
運行結果: