2014-09-21 83 views
2

在LDD3书中,它介绍了简单的睡眠(wait_event *()函数)和提前睡眠(prepare_to_wait()函数)。简单睡眠(使用wait_event _ *()函数)和高级睡眠(使用prepare_to_wait()函数)有什么区别?

如果我的理解是正确的,wait_queue_t似乎是一个过程条目,但wait_queue_head_t似乎是等待队列中存储的哪个(wait_queue_t)被添加的进程列表中..

所以,说到我的混淆了什么情况下,我应该使用wait_event _ *()函数与prepare_to_wait并指定等待进程。

我可以说的唯一原因是我可以在睡觉前指定过程状态而不是简单的睡眠。但是,简单的睡眠确实提供了可中断和不可中断的wait_event功能。所以,我有点困惑,为什么我们需要从设计和实现的角度来看两者。谢谢。

回答

5

这是wait_event()简化)实施:

#define wait_event(wq, condition) 
{ 
    DEFINE_WAIT(wait); 
    for (;;) { 
     prepare_to_wait(&wq, &wait, TASK_UNINTERRUPTIBLE); 
     if (condition) 
      break; 
     schedule(); 
    } 
    finish_wait(&wq, &wait); 
} 

如果此实现(或其他许多wait_event_*变种之一)为你工作,那么你应该使用它。

但是,可能有些情况下需要对此等待循环进行更多的控制。 例如,假设您想等待某些数据在缓冲区中可用并返回,并且这两个操作都需要在锁定下完成,并且检查数据删除数据需求是一个原子操作,也就是说,两者必须在相同的锁定下完成,而不需要解锁。 然后,你将不得不像上面这样修改上面的循环:

void my_own_wait(...) 
{ 
    DEFINE_WAIT(wait); 
    spin_lock(&lock); 
    while (!some_data_available()) { 
     prepare_to_wait(&wq, &wait, TASK_xxx); 
     spin_unlock(&lock); 
     schedule(); 
     spin_lock(&lock); 
     finish_wait(&wq, &wait); 
    } 
    take_data(); 
    spin_unlock(&lock); 
} 
+0

嗨,CL。感谢您的回应。然而,我看起来像我仍然可以使用wait_event将它放在my_own_wait实现...唯一的区别是,我可以把条件放在while循环中而不是在wait_event()中使用condition参数... – rickhau 2014-09-23 03:04:26

+0

在现实世界中,事情往往比'my_own_wait'更复杂;这同样适用于'wait_event'(它多次使用'condition')。但是,如果你的代码*不能正确的使用'wait_event',那么一定要用它。 – 2014-09-23 06:49:09

+0

根据ldd3,除非将'schedule()'包装在'if(!some_data_available())'中,否则会有一场竞赛。 (在有些数据可用的情况下,有人试图唤醒我们,在while检查之后和prepare_to_wait()之前)http://www.makelinux.net/ldd3/chp-6-sect-2 – ted 2017-04-13 13:23:15