Linux kernel 简单睡眠(使用wait_event_*()函数)和高级睡眠(使用prepare_to_wait()函数)之间有什么区别?

Linux kernel 简单睡眠(使用wait_event_*()函数)和高级睡眠(使用prepare_to_wait()函数)之间有什么区别?,linux-kernel,linux-device-driver,embedded-linux,Linux Kernel,Linux Device Driver,Embedded Linux,在LDD3书中,它介绍了简单睡眠(wait_event*()函数)和高级睡眠(prepare_to_wait()函数) 如果我的理解是正确的,wait_queue_t似乎是一个进程条目,而wait_queue_head_t似乎是一个等待队列,用于存储正在添加的进程列表(wait_queue_t) 因此,我感到困惑的是,在什么情况下应该使用wait_event_*()函数,而不是使用prepare_to_wait来指定等待过程 我能说出来的唯一原因是,我可以在睡眠前指定进程状态,而不是简单睡眠。然

在LDD3书中,它介绍了简单睡眠(wait_event*()函数)和高级睡眠(prepare_to_wait()函数)

如果我的理解是正确的,wait_queue_t似乎是一个进程条目,而wait_queue_head_t似乎是一个等待队列,用于存储正在添加的进程列表(wait_queue_t)

因此,我感到困惑的是,在什么情况下应该使用wait_event_*()函数,而不是使用prepare_to_wait来指定等待过程

我能说出来的唯一原因是,我可以在睡眠前指定进程状态,而不是简单睡眠。然而,简单睡眠确实提供了可中断和不可中断的等待事件功能


所以,从设计和实现的角度来看,我有点困惑为什么我们需要两者。谢谢。

这是
wait\u event()
的实现(简化了很多):

#定义等待事件(wq,条件)
{
定义等待(WAIT);
对于(;;){
准备等待(&wq,&wait,任务不间断);
如果(条件)
打破
附表();
}
完成等待(&wq,&wait);
}
如果此实现(或许多其他
wait\u event.*
变体之一)适合您,那么您应该直接使用它

然而,在某些情况下,您可能需要对这个等待循环进行更多的控制。 例如,假设您希望等待缓冲区中的某些数据可用,然后返回它,并且这两个操作都需要在锁下完成,检查数据和删除数据需要是一个原子操作,即,这两个操作都必须在同一个锁下完成,中间没有解锁。 然后必须修改上面的循环,如下所示:

void my_own_wait(…)
{
定义等待(WAIT);
旋转锁定(和锁定);
而(!某些数据可用(){
准备等待(&wq,&wait,任务xxx);
旋转/解锁(和锁定);
附表();
旋转锁定(和锁定);
完成等待(&wq,&wait);
}
以_数据()为例;
旋转/解锁(和锁定);
}

嗨,CL.谢谢您的回复。但是,我觉得我仍然可以使用wait_事件将其放入我自己的等待实现中。。。唯一的区别是我可以将条件放在while循环中,而不是在wait_event()中使用condition参数……在现实世界中,事情往往比
my_own_wait
更复杂;这同样适用于
等待事件
(它多次使用
条件
)。但是,如果您的代码在
wait\u事件
中正确运行,请务必使用它。根据ldd3,除非您将
schedule()
包装在
if(!某些可用数据())
中,否则将存在一场竞赛。(在一些数据可用的情况下,有人试图叫醒我们,在while检查之后,在prepare_to_wait()之前。)@ted查看
时间表()上方的三行内容。据我所知,问题如下:
while
检查条件并且没有可用数据,因此您进入loopbody。现在,在
prepare\u to\u wait
数据可用之前,我们会被叫醒。但是,我们还没有进入等待队列。执行此
prepare\u to\u wait
后,将任务置于睡眠状态(将状态设置为
task\u xxx
)。此时,我们错过了数据项的唤醒,就像在prepare\u to\u wait之前一样,让线程睡眠。请注意,在您的第一个代码片段中,条件检查介于prepare\u to\u wait和schedule之间。