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是非零掩码。
我正在写一个类似于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是非零掩码。