等待队列
等待队列
什么是等待队列
等待队列是内核实现阻塞和唤醒的内核机制。等待队列以循环链表为基础结构,链表头和链表项分别为等待队列头和等待队列元素。整个等待队列由等待队列头进行管理。
等待队列头使用结构体 wait_queue _head_t来表示, 等待队列头就是一个等待队列的头部,这个结构体定义在文件include/linux/wait.h里面,结构体内容如下:
struct wait queue head { spinlock_t lock; //自旋锁 struct list_head task_list; //链表头 } typedef struct wait_queue_head wait_queue_head_t;
定义并初始化等待队列头
方法一:
(1) 定义一个等待队列头:
wait_queue head t test_wq; //定义一个等待队列的头
初始化等待队列头:
(2)
可以使用 init waitqueue head 函数初始化等待队列头,函数原型如下:
方法二:
使用宏 DECLARE_WAIT_QUEUE_HEAD 来一次性完成等待队列头的定义和初始化。
原型:
DECLARE_WAIT_QUEUE_HEAD(wait_queue_head_t q);
#include <linux/kernel.h> #include <linux/init.h> #include <linux/moduleparam.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/version.h> #include <linux/kdev_t.h> #include <linux/cdev.h> #include <linux/uaccess.h> #include <linux/interrupt.h> #include <linux/wait.h> #define DEVICE_NAME "poll_dev" #define CLASS_NAME "poll_class" /*初始化一个队列头*/ static DECLARE_WAIT_QUEUE_HEAD(read_wq); static struct class *char_class; static struct device *char_device; int major; int flag = 0; char mes_buf[30]; int hello_open (struct inode *inode, struct file *file){ pr_info("hello_open\n"); return 0; } ssize_t hello_read(struct file *file, char __user *buf, size_t size, loff_t * loff_t){ if(file->f_flags & O_NONBLOCK){ if(flag == 0) return -EAGAIN; } /*进入休眠状态*/ wait_event_interruptible(read_wq, flag); if(copy_to_user(buf, mes_buf, strlen(mes_buf)) != 0) return -EFAULT; return strlen(mes_buf); } ssize_t hello_write (struct file *file, const char __user *buf, size_t size, loff_t *loff_t){ if(copy_from_user(mes_buf, buf, size) != 0){ printk(KERN_INFO "hello_write: copy_from_user error\n"); return -EFAULT; } printk(KERN_INFO "hello_write: %s\n", mes_buf); /*设置条件后,唤醒休眠任务*/ flag = 1; wake_up_interruptible(&read_wq); return size; } int hello_close(struct inode *inode, struct file *file){ printk(KERN_INFO "hello_close\n"); return 0; } static struct file_operations file_fops = { .owner = THIS_MODULE, .open = hello_open, .release = hello_close, .read = hello_read, .write = hello_write, }; static int __init hello_init(void){ major = register_chrdev(0, DEVICE_NAME, &file_fops); if(major < 0){ printk("key_irq_init register_chrdev failed\n"); return major; } char_class = class_create(THIS_MODULE, CLASS_NAME); if(IS_ERR(char_class)){ unregister_chrdev(major, DEVICE_NAME); printk("key_irq_init class_create failed\n"); return PTR_ERR(char_class); } char_device = device_create(char_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); if(IS_ERR(char_device)){ class_destroy(char_class); unregister_chrdev(major, DEVICE_NAME); printk("key_irq_init device_create failed\n"); return PTR_ERR(char_device); } printk("key_irq_init success\n"); return 0; } static void __exit hello_exit(void){ unregister_chrdev(major, DEVICE_NAME); device_destroy(char_class, MKDEV(major, 0)); class_destroy(char_class); printk("key_irq_exit success\n"); } module_init(hello_init); /*指定设备驱动入口函数*/ module_exit(hello_exit); /*指定设备驱动出口函数*/ MODULE_LICENSE("GPL");
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」