linux - 手动将进程置于 sleep 状态时是否存在竞争条件

标签 linux linux-kernel sleep race-condition device-driver

当我阅读 ldd3 第 6 章时,我对下面显示的代码感到困惑:

while (spacefree(dev) == 0) { /* full */ 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)
        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;
}

if (spacefree(dev) == 0)schedule() 之间是否存在竞争条件。如果 spacefree(dev) 函数在 if 语句刚刚结束时返回非零值,则进程可能会失去唯一被唤醒的机会。谁能告诉我这些代码背后的机制是什么?


顺便说一下,我在 Linux Kernel Development 中找到了另一个代码片段,它与上面的代码片段类似。然而,一些细节有所不同。

DEFINE_WAIT(wait);
add_wait_queue(q, &wait);
while (!condition) { /* condition is the event that we are waiting for */
    prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE);
    if (signal_pending(current))
        /* handle signal */
    schedule();
}
finish_wait(&q, &wait); 

最不同的是添加了 add_wait_queue() 函数,它没有出现在第一个代码片段中。

第二个区别是,在第二个片段的while 语句中,schedule() 之前没有条件测试。为什么?

第三个区别是signal_pending()函数的位置,一个在schedule()之前,一个在之后。

为什么会存在这样的差异?

最佳答案

来自 LDD3 第 6 章:

“通过在设置进程状态后检查我们的条件,我们可以免受所有 可能的事件顺序。如果我们等待的条件已经发生 在设置进程状态之前,我们注意到在此检查中并没有真正休眠。如果 此后发生唤醒,无论我们是否有,进程都可以运行 居然睡着了。”

关于linux - 手动将进程置于 sleep 状态时是否存在竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28029079/

相关文章:

c - sleep() 延迟输出直到结束

javascript - 在javascript中强制等待

python - arp中毒python失败(linux)

linux - Ubuntu 中 lampp 的文件权限

linux - 无法使用 wget 下载 git hub 搜索结果

c - 错误: ‘struct tty_driver’ has no member named ‘ioctl’

process - 内核:如何从进程的task_struct中查找所有线程?

测试在任何目标板上运行的 Linux 内核模块/驱动程序

c - sleep() 会干扰 scanf() 吗?

c - 在内核 3.10 上使用 netpoll