【问题标题】:Why does wait queue implementation wait on a loop until condition is met?为什么等待队列实现在循环中等待直到满足条件?
【发布时间】:2012-06-26 12:31:07
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: linux-kernel linux-device-driver


    【解决方案1】:

    等待队列的一个常见用例是中断。也许您的内核驱动程序当前正在等待三种不同的条件,每种条件都会被中断唤醒。

    这允许您的内核中断处理程序只唤醒所有的侦听器,然后他们可以确定他们的特定情况是否已经发生,或者他们是否应该唤醒。

    此外,您可能会收到虚假中断,因为可以共享中断,并且可以延迟和合并中断。


    添加一些代码以及不应该尝试更明确的代码。

    我在下面编写了一些代码,它们可能是内核驱动程序的一部分。中断处理程序只是要唤醒所有的侦听器。然而,并不是所有的听众都可以真正做到。两者都将被同一个中断唤醒,但它们都会在继续之前查看它们的特定条件是否已完成。

    // 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");
    }
    

    【讨论】:

    • 驱动程序可以在多个条件下等待吗?是不是一旦进程因为第一次等待而被挂起,其他的都不能执行了?所以我假设最多可以等待一次?
    • 我已经添加了一些代码。但是一个内核模块可以在任何一个时间点上执行多个线程。
    【解决方案2】:

    代码:

    #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() 再次使自己进入睡眠状态。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 同意控制可以通过。但我看不到“wait_event”中的循环如何解决文章中描述的同步问题。循环似乎更像是重试尝试..我只是想知道为什么
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-27
      • 2012-01-10
      • 2015-03-13
      • 2020-10-31
      • 2020-11-17
      • 1970-01-01
      相关资源
      最近更新 更多