【问题标题】:How do poll_wait() and wake_up_interruptible() work in sync?poll_wait() 和 wake_up_interruptible() 如何同步工作?
【发布时间】:2021-09-30 07:35:17
【问题描述】:

我正在编写一个类似于 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() 呼叫是否有可能永远被阻塞?

【问题讨论】:

    标签: c linux-kernel kernel-module


    【解决方案1】:

    我看到进程在轮询文件操作中被poll_wait() 置于睡眠状态...

    不,你错了。

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

    文件poll 操作的调用者将调用schedule() 并将当前进程置于睡眠状态。但是schedule() 只会在返回可用操作的掩码不拦截请求操作的掩码时被调用。

    如你所见,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,则操作返回(EPOLLIN | EPOLLRDNORM),并且不会执行休眠(以防轮询文件以进行读取)。

    如果在poll_wait 之后调用wake_up_interruptible,它将使进程返回可运行状态,因此schedule() 不会使其进入睡眠状态。调用schedule()后,将重新运行轮询操作,此时返回非零掩码。

    【讨论】:

    • 谢谢。因此,poll_wait() 执行 add_wait_queue(),poll() 的返回值作为是否执行 schedule() 的条件,然后 wake_up_interruptible 执行 remove_wait_queue()。对吗?
    • 是的,这个与在等待队列上定期等待的类比非常接近轮询实现。主要区别在于轮询进程可以一次等待多个等待队列(在多个文件上),因此当轮询终止时,应该从所有等待队列中删除该进程。
    猜你喜欢
    • 2019-08-31
    • 2012-04-23
    • 2011-10-27
    • 2015-04-12
    • 1970-01-01
    • 2010-11-03
    • 2016-09-10
    • 2018-05-25
    • 1970-01-01
    相关资源
    最近更新 更多