等待隊列示例

#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");

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章