【问题标题】:Why it is mandatory to check the condition in wait_event after prepare_to_wait?为什么在prepare_to_wait之后必须检查wait_event中的条件?
【发布时间】:2015-08-28 16:36:34
【问题描述】:

我试图了解在 linux 内核中如何实现 wait_event。 ldd3 中有一个代码示例,其中使用 prepare_to_wait (http://www.makelinux.net/ldd3/chp-6-sect-2) 解释了内部实现。

static int scull_getwritespace(struct scull_pipe *dev, struct file *filp)
{
    while (spacefree(dev) == 0) {
        DEFINE_WAIT(wait);

        up(&dev->sem);
        if (filp->f_flags & O_NONBLOCK)
            return -EAGAIN;
        PDEBUG("\"%s\" writing: going to sleep\n",current->comm);
        prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
        if (spacefree(dev) == 0)  // Why is this check necessary ??
            schedule(  );
        finish_wait(&dev->outq, &wait);
        if (signal_pending(current))
            return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
        if (down_interruptible(&dev->sem))
            return -ERESTARTSYS;
    }
    return 0;
}

在书中,解释如下。

然后是对缓冲区的强制性检查;我们必须处理这个案子 我们进入后缓冲区中的可用空间 while 循环(并删除了信号量),但在我们放自己之前 进入等待队列。如果没有该检查,如果阅读器进程是 能够在那个时候完全清空缓冲区,我们可能会错过 只有唤醒我们才能永远睡着。满意了 我们自己必须睡觉,我们可以调用 schedule。

我无法理解这段解释。如果 if (spacefree(dev) == 0) 在调用 schedule() 之前没有完成,我们将如何进入无限期休眠? 如果此强制性检查不存在,wakeup() 仍会将进程状态重置为 TASK_RUNNING 并安排返回,如下一段所述。

这个案例值得再看一遍:如果唤醒会发生什么 在 if 语句中的测试和调度调用之间发生了什么? 在这种情况下,一切都很好。唤醒将进程状态重置为 TASK_RUNNING 和计划返回——尽管不一定马上。 只要测试发生在进程将自身置于 等待队列并更改其状态,一切都会正常。

【问题讨论】:

    标签: linux-kernel linux-device-driver blockingqueue


    【解决方案1】:

    重要的是(最后一次)检查是在 prepare_to_wait() 被调用之后完成的。

    prepare_to_wait() 将指向当前进程的指针放入等待队列。如果唤醒发生在prepare_to_wait() 调用之前,唤醒将无法影响当前进程。

    【讨论】:

    • 啊……我现在明白了。谢谢你的解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 2015-08-19
    • 2021-10-31
    • 1970-01-01
    • 2018-10-21
    • 2016-01-16
    相关资源
    最近更新 更多