让我们考虑单处理器方案。
wait_event_interruptible()
(或其他等待API)在循环中等待,直到满足某个条件。
现在,由于linux将线程实现为单独的进程,因此我认为错误唤醒(wait_event*
在未满足条件的情况下被唤醒)表示程序/驱动程序出错。
我错了吗? - 是否存在可能发生并使用此类虚假唤醒的有效情况?换句话说,为什么要在wait_event*
实现中的循环中等待条件?
答案 0 :(得分:8)
等待队列的常见用例是中断。也许你的内核驱动程序当前正在等待三个不同的条件,每个条件都会被中断唤醒。
这允许你的内核中断处理程序唤醒所有侦听器,然后他们可以自己确定是否已经发生了特定情况,或者是否应该唤醒它们。
此外,您可以获得虚假中断,因为可以共享中断,并且因为中断被延迟和合并。
添加一些代码以及不应该更明确的内容。
我在下面编写了一些可能是内核驱动程序的代码。中断处理程序只是唤醒所有侦听器。但是,并非所有听众都可以完成。两者都会被同一个中断唤醒,但他们都会在继续之前查看他们的特定条件是否已完成。
// Registered interrupt handler
static irqreturn_t interrupt_handler(void *private) {
struct device_handle *handle = private;
wake_up_all(&handle->wait);
}
// Some Kernel Thread
void program_a(struct device_handle * handle) {
wait_event_interruptible(&handle->wait, hardware_register & 0x1);
printk("program_a finished\n");
}
// Some other kernel thread
void program_b(struct device_handle * handle) {
wait_event_interruptible(&handle->wait, hardware_register & 0x2);
printk("program_b finished\n");
}
答案 1 :(得分:3)
代码:
#define __wait_event(wq, condition) \
do { \
DEFINE_WAIT(__wait); \
\
for (;;) { \
prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
schedule(); \
} \
finish_wait(&wq, &__wait); \
} while (0)
(除了内核是先发制人的事实......)
我假设你指的是上面的无限'for'循环? 如果是这样,它的主要原因是:
一旦唤醒,代码就不会对状态做出任何假设。只是被唤醒不意味着你正在等待的事件实际发生了;你必须重新检查。这正是循环实现的目标。如果'if'条件成立(在正常情况下它应该),它退出循环,否则(虚假唤醒)它通过调用schedule()使自己再次进入睡眠状态。
答案 2 :(得分:0)
即使在单处理器场景中,内核也是抢占式的,即控件可以随时传递给其他线程/进程,因此行为与多处理器相同。 关于丢失等待问题的良好讨论在这里: http://www.linuxjournal.com/node/8144/print