[转帖]wait_event_interruptible() 和 wake_up()的使用_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2320 | 回复: 0   主题: [转帖]wait_event_interruptible() 和 wake_up()的使用        下一篇 
xuefeng
注册用户
等级:上士
经验:315
发帖:69
精华:0
注册:2011-8-17
状态:离线
发送短消息息给xuefeng 加好友    发送短消息息给xuefeng 发消息
发表于: IP:您无权察看 2014-12-10 9:23:31 | [全部帖] [楼主帖] 楼主

1. 关于 wait_event_interruptible() 和 wake_up()的使用

读一下wait_event_interruptible()的源码,不难发现这个函数先将
当前进程的状态设置成TASK_INTERRUPTIBLE,然后调用schedule(),
而schedule()会将位于TASK_INTERRUPTIBLE状态的当前进程从runqueue
队列中删除。从runqueue队列中删除的结果是,当前这个进程将不再参
与调度,除非通过其他函数将这个进程重新放入这个runqueue队列中,
这就是wake_up()的作用了。

由于这一段代码位于一个由condition控制的for(;;)循环中,所以当由
shedule()返回时(当然是被wake_up之后,通过其他进程的schedule()而
再次调度本进程),如果条件condition不满足,本进程将自动再次被设
置为TASK_INTERRUPTIBLE状态,接下来执行schedule()的结果是再次被
从runqueue队列中删除。这时候就需要再次通过wake_up重新添加到
runqueue队列中。

如此反复,直到condition为真的时候被wake_up.

可见,成功地唤醒一个被wait_event_interruptible()的进程,需要满足:

   在 1)condition为真的前提下,2) 调用wake_up()。

所以,如果你仅仅修改condition,那么只是满足其中一个条件,这个时候,
被wait_event_interruptible()起来的进程尚未位于runqueue队列中,因
此不会被 schedule。这个时候只要wake_up一下就立刻会重新进入运行调度。

2. 关于wait_event_interruptible的返回值

根据 wait_event_interruptible 的宏定义知:

   1) 条件condition为真时调用这个函数将直接返回0,而当前进程不会
      被 wait_event_interruptible和从runqueue队列中删除。

   2) 如果要被wait_event_interruptible的当前进程有nonblocked pending
      signals, 那么会直接返回-ERESTARTSYS(i.e. -512),当前进程不会
      被wait_event_interruptible 和从runqueue队列中删除。

   3) 其他情况下,当前进程会被正常的wait_event_interruptible,并从
      runqueue队列中删除,进入TASK_INTERRUPTIBLE状态退出运行调度,
      直到再次被唤醒加入runqueue队列中后而参与调度,将正常返回0。

附1:wait_event_interruptible  宏

#define wait_event_interruptible(wq, condition) \
({ \
      int __ret = 0; \
      if (!(condition)) \
      __wait_event_interruptible(wq, condition, __ret); \
      __ret; \
})


注: C语言中{a,b, ..., x}的的值等于最后一项,即x,因此上述
宏的值是 __ret。

  
附2:wait_event_interruptible()和 wake_up的等效代码

wait_event_interruptible(wq, condition) /*等效没有考虑返回值*/
{
      if (!(condition))
      {
            wait_queue_t _ _wait;
            init_waitqueue_entry(&_ _wait, current);
            add_wait_queue(&wq, &_ _wait);
            for (;;)
            {
                  set_current_state(TASK_INTERRUPTIBLE);
                  if (condition)
                  break;
                  schedule(); /* implicit call: del_from_runqueue(current)*/
            }
            current->state = TASK_RUNNING;
            remove_wait_queue(&wq, &_ _wait);
      }
}
void wake_up(wait_queue_head_t *q)
{
      struct list_head *tmp;
      wait_queue_t *curr;
      list_for_each(tmp, &q->task_list)
      {
            curr = list_entry(tmp, wait_queue_t, task_list);
            wake_up_process(curr->task);
            /* implicit call: add_to_runqueue(curr->task);*/
            if (curr->flags)
            break;
      }
}


--转自 北京联动北方科技有限公司




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论