http://blog.sina.com.cn/s/blog_4770ef020101h48l.html
功能:唤醒注册到等待队列上的进程
原型:
#include
void wake_up_interruptible (wait_queue_head_t *q);
说明:
唤醒 q
指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。
变量:
q : 等待队列变量指针。
最近在学习驱动时有一个问题始终想不明白,为什么wait_event_interruptible(button_waitq,
ev_press)需要一个全局变量来记住中断的发生?
在驱动中实现读取操作时,使用了
- wait_event_interruptible(button_waitq, ev_press);
在中断函数中使用了如下语句唤醒:
- ev_press =
1; //表示中断发生了 - wake_up_interruptible(&button_waitq); //唤醒休眠的进程
这样的话,中断能正确读取到。我分别尝试了屏蔽ev_press =
1;和wake_up_interruptible(&button_waitq);代码,发现中断不能正常产生。
查找资料,阅读源代码。
- #define wait_event_interruptible(wq,
condition) \ - ({
\ - int
__ret =
0;
\ - if
(!(condition)) \ - __wait_event_interruptible(wq,
condition, __ret);\ - __ret;
\ - })
- #define __wait_event_interruptible(wq, condition,
ret) \ - do
{ \ - DEFINE_WAIT(__wait); \
- \
- for
(;;)
{ \ - prepare_to_wait(&wq,
&__wait,
TASK_INTERRUPTIBLE); \ - if
(condition) \ - break; \
- if
(!signal_pending(current))
{ \ - schedule(); \
- continue; \
- } \
- ret
=
-ERESTARTSYS; \ - break; \
- } \
- finish_wait(&wq,
&__wait); \ - } while (0)
__wait_event_interruptible()首先定义并初始化一个wait_queue_t变量__wait,其中数据为当前进程current,并把__wait入队。
在无限循环中,__wait_event_interruptible()将本进程置为可中断的挂起状态,反复检查condition是否成立,如果成立则退出,如果不成立则继续休眠;条件满足后,即把本进程运行状态置为运行态(此时如果不执行下面的函数
wake_up_interruptible,上面wait_event_interruptible还会继续休眠),并将__wait从等待队列中清除掉,从而进程能够调度运行。如果进程当前有异步信号(POSIX的),则返回-ERESTARTSYS。
- //唤醒 q
指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。