wake_up_interruptible 函数

来源:互联网 发布:python split去掉空格 编辑:程序博客网 时间:2024/05/20 21:19
功能:唤醒注册到等待队列上的进程

原型
    #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 指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。
  2. wake_up_interruptible (wait_queue_head_t *q);
我是这样考虑的:read 调用wait_event_interruptible(button_waitq),我觉得一个参数就够了。不判断什么条件,直接休眠,下面用wake_up_interruptible(&button_waitq)直接唤醒。这样看起来很简单。
不知道内核这样设计是基于什么原因?
上下文切换(Context Switching):在多任务系统中,上下文切换是指CPU的控制权由运行任务转移到另外一个就绪任务时所发生的事件,当前运行任务转为就绪(或者挂起、删除)状态,另一个被选定的就绪任务成为当前任务。上下文切换包括保存当前任务的运行环境,恢复将要运行任务的运行环境。上下文的内容依赖于具体的CPU。
 
http://www.groad.net/bbs/read.php?tid-1336.html
http://www.100ask.net/forum/showtopic-4322.aspx
原创粉丝点击