驱动 poll 接口实现原理




(2005-05-02 15:45:26)
标签:

杂谈

分类: MSN搬家

为了支持应用层的 select 系统调用,驱动需要实现 poll 方法。标准实现如下:

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

   
    int left = (dev->rp + dev->buffersize - dev->wp) % dev->buffersize;

    poll_wait(filp, &dev->inq, wait);
    poll_wait(filp, &dev->outq, wait);
    if (dev->rp != dev->wp) mask |= POLLIN | POLLRDNORM;
    if (left != 1) mask |= POLLOUT | POLLWRNORM;

    return mask;
}

很简单的代码,问题是怎么实现 select 的读/写查询的?除非可读或写或超时,select 是阻塞的,但是我们这个 poll 方法阻塞在哪里呢?如果阻塞在 poll_wait,那假如第1个(读)poll_wait 阻塞了,第2个(写)poll_wait 得不到调用,此时有空间可写 select 函数也无法知晓;如果是阻塞在外面,poll_wait 只是一个登记的作用,那将来 select 怎么区分最终到底是可读还是可写呢?毕竟 poll_wait 操纵的是同一张表。

其实,阻塞位于 linux-2.4.x/fs/select.c 的 do_select() 函数,大概顺序是:
1:初始化 poll_table 这张表
2:然后依次调用每个文件的 poll 方法
3:poll 方法调用的 poll_wait() 里会调用 init_waitqueue_entry() 和 add_wait_queue(),把当前的进程挂到驱动提供的wait_queue_head_t中
3:假如能读或能写或有信号,就返回
4:调用 schedule_timeout 睡眠
5:当前进程醒来满足:超时,有信号(TASK_INTERRUPTIBLE),驱动唤醒(wake_up_interruptible)
6:继续步骤2,注意反复调用 poll 方法,不会造成 poll_table 的重复插入,因为以后调用 poll 方法的 poll_table 参数为空,此时系统实际上只要获得 mask 来判断到底是可读还是可写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值