为什么等待队列实现在循环中等待直到满足条件?

时间:2012-06-25 06:47:36

标签: linux-kernel linux-device-driver

让我们考虑单处理器方案。

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

现在,由于linux将线程实现为单独的进程,因此我认为错误唤醒(wait_event*在未满足条件的情况下被唤醒)表示程序/驱动程序出错。

我错了吗? - 是否存在可能发生并使用此类虚假唤醒的有效情况?换句话说,为什么要在wait_event*实现中的循环中等待条件?

3 个答案:

答案 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