2015-05-14 228 views
7

在LDD3,我看到这样的代码为什么我们需要在poll中调用poll_wait?

static unsigned int scull_p_poll(struct file *filp, poll_table *wait) 
{ 
    struct scull_pipe *dev = filp->private_data; 
    unsigned int mask = 0; 

    /* 
    * The buffer is circular; it is considered full 
    * if "wp" is right behind "rp" and empty if the 
    * two are equal. 
    */ 
    down(&dev->sem); 
    poll_wait(filp, &dev->inq, wait); 
    poll_wait(filp, &dev->outq, wait); 
    if (dev->rp != dev->wp) 
     mask |= POLLIN | POLLRDNORM; /* readable */ 
    if (spacefree(dev)) 
     mask |= POLLOUT | POLLWRNORM; /* writable */ 
    up(&dev->sem); 
    return mask; 
} 

但它说poll_wait不会等待,将立即返回。那为什么我们需要打电话呢?为什么我们不能只返回面具?

回答

10

poll_wait将您的设备(由“struct file”表示)添加到可以唤醒进程的设备列表中。

想法是,该进程可以使用轮询(或选择或epoll等)来添加一堆文件描述符到它希望等待的列表中。每个驱动程序的轮询条目都会被调用。每个人都将其自身(通过poll_wait)添加到服务员列表中。

然后核心内核在一个地方阻塞进程。这样,任何一个设备都可以唤醒进程。如果您返回非零掩码位,则表示这些“就绪”属性(可读/可写/等)现在应用现在

所以,在伪代码,它大致是这样的:当有它正在等待发生在任何FD的的预期事件或它击中超时

foreach fd: 
    find device corresponding to fd 
    call device poll function to setup wait queues (with poll_wait) and to collect its "ready-now" mask 

while time remaining in timeout and no devices are ready: 
    sleep 

return from system call (either due to timeout or to ready devices) 
+0

然后做的过程中睡眠时? – demonguy

+0

@demonguy查看我的更新回答 –

+0

您的意思是说,来自用户空间的查询调用会阻止进程,对不对? – demonguy

-1

poll_wait触发。

检查掩码以了解哪个事件触发了poll_wait。如果您不希望poll_wait触发此类事件,则可以在注册文件描述符的同时对其进行配置以轮询fd。

+1

这是完全错误的。 'poll_wait'根本不'触发'。它只是将一个等待队列添加到'poll_table'。 – EML

2

pollfile_operation睡觉,如果你回到0

这是混淆了我。

当你返回非零时,它意味着某个事件被触发了,并且它被唤醒。

一旦你看到这一点,很明显,有什么东西必须绑定到等待队列的过程,那东西是poll_wait

还要记住struct file代表“进程和打开文件之间的连接”,而不仅仅是文件系统文件,因此它包含用于标识进程的pid。

以最小的可运行的例子播放也可能有助于明确的东西:https://stackoverflow.com/a/44645336/895245