等待队列示例

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:16   1292   0
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>

#include <asm/io.h>
#include <asm/uaccess.h>

static dev_t dev_id;
static struct cdev *button_dev;
static struct class *button_class;

/* 定义并初始化一个等待队列头 */
static DECLARE_WAIT_QUEUE_HEAD(button_wq_head);
static int button_conditon;
static int button_val;

static irqreturn_t button_irq(int irq, void *data)
{
    /* 判断等待队列中是否有等待元素 */
 //也就是判断一个等待队列是否可用:
    if(!waitqueue_active(&button_wq_head))
        return IRQ_HANDLED;

    /* 读取按键值 */
    button_val = gpio_get_value(S5PV210_GPH0(2));

    /* 唤醒等待队列 */
 
 /***
 wake_up可以唤醒处于TASK_UNINTERRUPTIBLE和TASK_INTERRUPTIBLE
 状态的进程
 
 wake_up_interruptible只能唤醒处于TASK_INTERRUPTIBLE状态的进程

 TASK_INTERRUPTIBLE:处于等待队伍中,等待资源有效时唤醒
 (比方等待键盘输入、socket连接、信号等等),
 但能够被中断唤醒.普通情况下,进程列表中的绝大多
 数进程都处于TASK_INTERRUPTIBLE状态.毕竟皇帝仅仅有一个
 (单个CPU时),后宫佳丽几千;假设不是绝大多数进
 程都在睡眠,CPU又怎么响应得过来.


 TASK_UNINTERRUPTIBLE:处于等待队伍中,等待资源有效时唤醒
 (比方等待键盘输入、socket连接、信号等等),
 但不能够被中断唤醒.
 ***/
    button_conditon = 1;
    wake_up_interruptible(&button_wq_head);

    return IRQ_HANDLED;
}

static int button_open(struct inode *inode, struct file *file)
{
    int ret;
    
    ret = request_irq(IRQ_EINT2, button_irq, IRQF_TRIGGER_FALLING, "button_irq", NULL);

    return 0;
}

static ssize_t button_read(struct file *file, char __user *data, size_t size, loff_t *loff)
{
    int ret;
    int val;

    /* 睡眠等待 */
    button_conditon = 0;
    wait_event_interruptible(button_wq_head, button_conditon);
    button_conditon = 0;
    
    val = button_val;
    ret = copy_to_user(data, &val, sizeof(val));

    return sizeof(val);
}

static int button_release(struct inode *inode, struct file *file)
{
    free_irq(IRQ_EINT2, NULL);

    return 0;
}

static struct file_operations button_fops = {
 .owner      = THIS_MODULE,
    .open       = button_open,
    .read       = button_read,
    .release    = button_release,
};

static __init int button_init(void)
{
    /* 申请设备号 */
    alloc_chrdev_region(&dev_id, 1, 1, "button");

    /* 分配字符设备 */
    button_dev = cdev_alloc();

    /* 设置字符设备 */
    cdev_init(button_dev, &button_fops);

    /* 注册字符设备 */
    cdev_add(button_dev, dev_id, 1);

    /* 创建设备节点 */
 button_class = class_create(THIS_MODULE, "button"); //创建类
 device_create(button_class, NULL, dev_id, NULL, "button"); //创建设备节点

    gpio_request(S5PV210_GPH0(2), "button");

    return 0;
}

static __exit void button_exit(void)
{
    /* 注销设备节点 */
    device_destroy(button_class, dev_id);
    class_destroy(button_class);

    /* 注销字符设备 */
    cdev_del(button_dev);
    kfree(button_dev);

    /* 注销注册的设备号 */
    unregister_chrdev_region(dev_id, 1);

    gpio_free(S5PV210_GPH0(2));
}

module_init(button_init);
module_exit(button_exit);

MODULE_LICENSE("GPL");

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP