等待队列

发布时间 2023-12-19 20:48:26作者: zxz-FINE

等待队列

什么是等待队列
等待队列是内核实现阻塞和唤醒的内核机制。等待队列以循环链表为基础结构,链表头和链表项分别为等待队列头和等待队列元素。整个等待队列由等待队列头进行管理。
等待队列头使用结构体 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");