poll_wait() 和 wake_up_interruptible() 如何同步工作?

How do poll_wait() and wake_up_interruptible() work in sync?

我正在写一个类似于uio的字符设备。 https://elixir.bootlin.com/linux/latest/source/drivers/uio/uio.c。我看到该进程在轮询文件操作中被 poll_wait() 置于睡眠状态,并在发生中断时被唤醒 wake_up_interruptible()。我不明白 wait 和 wake_up 调用是如何同步的。

考虑这个案例。

poll()系统调用在用户空间完成。

uio_poll()被执行。

就在 poll_wait() 之前,发生中断并 wake_up_interruptible() 完成。

现在poll_wait()被执行了。

如果没有进一步的中断,poll() 呼叫是否可能永远被阻止?

I see that the process is put to sleep by poll_wait() in poll file operation ...

不对,你看错了。

poll_wait的调用只是将当前进程的状态设置为非运行nable,并将当前进程添加到等待队列中。这两个操作都是非休眠的,所以 poll_wait returns。之后,poll 文件操作 继续 直到结束并且 return 是可用操作的掩码。

文件poll操作的调用者将调用schedule()并将当前进程置于睡眠状态。但是 schedule() 仅在 return 可用 掩码 操作 不拦截 掩码的情况下才会被调用=39=]请求次操作。

如您所见,poll 方法首先调用 poll_wait 然后才计算掩码:

poll_wait(filep, &idev->wait, wait);
if (listener->event_count != atomic_read(&idev->event))
    return EPOLLIN | EPOLLRDNORM;
return 0;

因此,如果在 poll_wait 之前调用 wake_up_interruptible,则操作 returns (EPOLLIN | EPOLLRDNORM),并且不会执行休眠(如果轮询文件以供读取)。

如果在 poll_wait 之后调用 wake_up_interruptible,它将 return 进程进入 运行nable 状态,所以 schedule() 不会它进入睡眠状态。调用schedule()后,轮询操作将重新运行,此时它return是非零​​掩码。