Linux使用wake_up_interruptible()唤醒注册到等待队列上的进程

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)需要一个全局变量来记住中断的发生?
在驱动中实现读取操作时,使用了
  1. wait_event_interruptible(button_waitq, ev_press);
在中断函数中使用了如下语句唤醒:
  1. ev_press = 1;  //表示中断发生了
  2. wake_up_interruptible(&button_waitq);  //唤醒休眠的进程
这样的话,中断能正确读取到。我分别尝试了屏蔽ev_press = 1;和wake_up_interruptible(&button_waitq);代码,发现中断不能正常产生。

查找资料,阅读源代码。
  1. #define wait_event_interruptible(wq, condition)          \
  2. ({                                                       \
  3.     int __ret = 0;                                       \
  4.     if (!(condition))                                    \
  5.         __wait_event_interruptible(wq, condition, __ret);\
  6.     __ret;                                               \
  7. })
  1. #define __wait_event_interruptible(wq, condition, ret)                        \
  2. do {                                                                        \
  3.         DEFINE_WAIT(__wait);                                                \
  4.                                                                         \
  5.         for (;;) {                                                        \
  6.                 prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);        \
  7.                 if (condition)                                                \
  8.                         break;                                                \
  9.                 if (!signal_pending(current)) {                                \
  10.                         schedule();                                        \
  11.                         continue;                                        \
  12.                 }                                                        \
  13.                 ret = -ERESTARTSYS;                                        \
  14.                 break;                                                        \
  15.         }                                                                \
  16.         finish_wait(&wq, &__wait);                                        \
  17. } while (0)
__wait_event_interruptible()首先定义并初始化一个wait_queue_t变量__wait,其中数据为当前进程current,并把__wait入队。
    在无限循环中,__wait_event_interruptible()将本进程置为可中断的挂起状态,反复检查condition是否成立,如果成立则退出,如果不成立则继续休眠;条件满足后,即把本进程运行状态置为运行态(此时如果不执行下面的函数 wake_up_interruptible,上面wait_event_interruptible还会继续休眠),并将__wait从等待队列中清除掉,从而进程能够调度运行。如果进程当前有异步信号(POSIX的),则返回-ERESTARTSYS。
  1. //唤醒 q 指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。
posted @ 2015-01-07 15:04  静之深  阅读(5350)  评论(0编辑  收藏  举报