3

让我们考虑一个单处理器场景。

wait_event_interruptible()(或其他等待 API)循环等待,直到满足某个条件。

现在,由于 linux 将线程实现为单独的进程,我相信错误唤醒(在wait_event*未满足条件的情况下唤醒)表明程序/驱动程序中存在错误。

我错了吗?- 是否有任何有效的场景可以发生和使用这种错误唤醒?换句话说,为什么要在实现的循环wait_event*中等待条件?

4

3 回答 3

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");
}
于 2012-06-26T02:22:46.743 回答
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() 再次使自己进入睡眠状态。

于 2012-06-26T02:13:47.140 回答
0

即使在单处理器情况下,内核也是抢占式的,即控制可以随时传递给其他线程/进程,因此行为与多处理器相同。关于丢失等待问题的良好讨论在这里: http ://www.linuxjournal.com/node/8144/print

于 2012-06-25T10:47:12.570 回答