Linux驱动中的wait_event_interruptible()与wake_up_interruptible()

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) 

Linux驱动中的wait_event_interruptible()与wake_up_interruptible()

DECLARE_WAIT_QUEUE_HEAD(wq)

  生成一个等待队列头wait_queue_head_t,名字为wq.

wait_event_interruptible(wq, condition):

  使他们的调用进程在等待队列上睡眠, 直到满足给定条件为止.

wake_up_interruptible(x)

  唤醒等待队列中的进程, 并把它们的状态设置为TASK_RUNNING.

这三个宏/函数通常一起出现, 主要用于中断处理/进程同步/定时等.

下面是我在按键中断中使用这三个宏/函数的代码:
#include <linux/interrupt.h>

/* 中断事件标志, 中断服务程序将它置1,btn_read将它清0 */
static volatile int ev_press = 0;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

/* handler, 中断处理函数, 当中断发生时该函数会被调用. */
static irqreturn_t btn_handler(int irq, void *dev_id)
{
	......
	ev_press = 1;	/* 表示中断发生了 */
	wake_up_interruptible(&button_waitq);	/* 唤醒休眠的进程 */

	return ...
}

int btn_open(struct inode *pinode, struct file *pfile)
{
	......
	/**
	 * 在这里申请中断, 告诉Linux所申请的中断号以及当中断发生时的中断处理函数.
	 */
	request_irq(pins_desc[0].irq, btn_handler, IRQF_TRIGGER_HIGH | IRQF_SHARED, 
						"ybk_btn", &pins_desc[0]);
	......

	return 0;
}

int btn_close(struct inode *pinode, struct file *pfile)
{
	/* 撤销之前的在btn_open()函数中的中断申请操作 */
	free_irq(pins_desc[0].irq, &pins_desc[0]);
	return 0;
}

ssize_t btn_read(struct file *pfile, char __user *userbuf, size_t size, loff_t *loff)
{
	/* 如果没有按键动作, 休眠 */
	wait_event_interruptible(button_waitq, ev_press);

	/* 如果有按键动作, 返回键值 */
	copy_to_user(userbuf, &gkey_val, sizeof(gkey_val));
	ev_press = 0;

	return size;
}

上面的btn_open()和btn_close()分别申请和撤销了一个中断, 不在本文讨论范围, 有了这两个函数我们才可以正常的使用中断以及演示这三个宏/函数的功能.

我们在代码的开头, 定义了两个变量:

  1. volatile int ev_press = 0; 用于wait_event_interruptible(wq, condition)中的condition, 当该调用进程被唤醒时, wait_event_interruptible会检查condition值是否为true, 为true会接着往下走, 为false时将继续休眠.
  2. DECLARE_WAIT_QUEUE_HEAD(button_waitq); 生成一个等待队列头wait_queue_head_t,名字为button_waitq. 该变量将会被放入wait_event_interruptible(wq, condition)函数与wake_up_interruptible(wq)宏中做参数. 相当于一个枢纽/关键字的作用, 因为有该变量的存在. 所以wait_event_interruptible和wake_up_interruptible成对使用且一一对应(不会跑偏了).

我们在btn_read()函数中使用了wait_event_interruptible(button_waitq, ev_press);
  当应用层程序使用read()函数而最终调用到btn_read()时, 会因为wait_event_interruptible(button_waitq, ev_press);而被CPU挂起, 进入休眠状态.

我们在btn_handler()函数中使用了wake_up_interruptible(&button_waitq);
  当有按键被按下时, 我们的btn_handler()函数将会被CPU所调用, 当运行到wake_up_interruptible(&button_waitq);函数时, 进程将会被唤醒. 此时的进程将会检查wait_event_interruptible(button_waitq, ev_press);函数中的ev_press是否为1/true, 当为真时, 进程将继续往下跑, 最终应用层的read()函数获得从驱动层传回来的结果.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安河桥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值