让我们考虑一个单处理器场景。
wait_event_interruptible()
(或其他等待 API)循环等待,直到满足某个条件。
现在,由于 linux 将线程实现为单独的进程,我相信错误唤醒(在wait_event*
未满足条件的情况下唤醒)表明程序/驱动程序中存在错误。
我错了吗?- 是否有任何有效的场景可以发生和使用这种错误唤醒?换句话说,为什么要在实现的循环wait_event*
中等待条件?
让我们考虑一个单处理器场景。
wait_event_interruptible()
(或其他等待 API)循环等待,直到满足某个条件。
现在,由于 linux 将线程实现为单独的进程,我相信错误唤醒(在wait_event*
未满足条件的情况下唤醒)表明程序/驱动程序中存在错误。
我错了吗?- 是否有任何有效的场景可以发生和使用这种错误唤醒?换句话说,为什么要在实现的循环wait_event*
中等待条件?
等待队列的一个常见用例是中断。也许您的内核驱动程序当前正在等待三种不同的条件,每个条件都会被中断唤醒。
这允许您的内核中断处理程序只唤醒所有侦听器,然后他们可以确定它们的特定条件是否已经发生,或者它们是否应该唤醒。
此外,您可能会收到虚假中断,因为可以共享中断并且因为中断被延迟和合并。
添加一些代码以及不尝试更明确的内容。
我在下面编写了一些代码,这些代码可能是内核驱动程序的一部分。中断处理程序只是要唤醒所有的侦听器。然而,并不是所有的听众都可以真正做到。两者都将被同一个中断唤醒,但他们都会在继续之前查看他们的特定条件是否完成。
// 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");
}
代码:
#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() 再次使自己进入睡眠状态。
即使在单处理器情况下,内核也是抢占式的,即控制可以随时传递给其他线程/进程,因此行为与多处理器相同。关于丢失等待问题的良好讨论在这里: http ://www.linuxjournal.com/node/8144/print