等待队列demo
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/uaccess.h>
int test_condition = 0;
module_param(test_condition, int, 0644);
static int wait_num = 0;
//定义等待队列头
//wait_queue_head_t my_wait;
//init_waitqueue_head(&my_wait);
/*使用宏定义*/
struct task_struct *wait_queue_task = NULL;
struct task_struct *wake_up_task = NULL;
static DECLARE_WAIT_QUEUE_HEAD(my_wait);
wait_queue_t *wq_entry=NULL;
static int wait_queue_thread(void *data)
{
wait_queue_head_t *wait_tmp = (wait_queue_head_t *)data;
DECLARE_WAITQUEUE(wait_task,current);
wq_entry = &wait_task;
add_wait_queue(wait_tmp, &wait_task);
wait_num++;
printk("TEST:wait_task will add to queue:%d\n", wait_num);
wait_event(my_wait, test_condition);
wait_num--;
test_condition = 0;
printk("TEST:wait_task after wait event:%d\n", wait_num);
return 0;
}
static int wake_up_thread(void *data)
{
wait_queue_head_t *wait_tmp = (wait_queue_head_t *)data;
/* 线程中需要注意不能一直不退出,否则kthread_stop会阻塞死等 */
while(!kthread_should_stop())
{
printk("TEST:wake_up wait_num:%d,condition:%d\n", wait_num, test_condition);
if(test_condition > 0)
{
wake_up(wait_tmp);
}
msleep(5000);
}
return 0;
}
static int test_init(void)
{
wait_queue_task = kthread_run(wait_queue_thread, (void *)(&my_wait), "wait_queue_thread");
if (wait_queue_task == NULL) {
pr_err("wait_queue_task_create failed\n");
return -1;
}
wake_up_task = kthread_run(wake_up_thread, (void *)(&my_wait), "wake_up_thread");
if (wake_up_task == NULL) {
pr_err("wait_queue_task_create failed\n");
return -1;
}
return 0;
}
module_init(test_init);
static void test_exit(void)
{
int ret;
/*kernel_stop更像一个等待子线程结束的函数,结束了再卸载模块,并没有强制停止的功能*/
ret = kthread_stop(wake_up_task);
printk("wake_up_task is stop...%d\n", ret);
/* 已经唤醒后的无法再次移除 */
remove_wait_queue(&my_wait, wq_entry);
/* 已经wait的线程虽然已经被移除,但线程本身还在等待,需要手动唤醒,不然kthread_stop还是会阻塞 */
test_condition = 1;
printk("remove_wait_queue...%d\n",test_condition);
ret = kthread_stop(wait_queue_task);
printk("wait_queue_task is stop...%d\n", ret);
return;
}
module_exit(test_exit);
MODULE_LICENSE("GPL V2");