wait_event_interruptible()与wake_up()的使用

20 篇文章 0 订阅
  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一下就立刻会重新进入运行调度。

  • 关于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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值