读书笔记:LLD3(2)非堵塞型I/O
非堵塞型I/O:当数据不可用时,进程调用read或write系统调用时,进程不会堵塞,会立即返回,即使现在没有数据可读或者可写。
非堵塞型I/O分为 两种:显示和隐式的。
显示:即将filp->f_flags中的O_NONBLOCK置位。
隐式:在调用read或write系统调用之前,先调用poll select或者epoll 查询该文件是否有数据可读写。
注释:O_NONBLOCK只对read write 和open有效。
poll select和epoll在调用过程中会堵塞。
poll 和 select(轮询):
用来查询某个或者多个文件描述符上的读取或写入是否会被堵塞。如果现在没有可以读写的文件描述符,则堵塞等待直到有可读写的文件描述符。如果有,则直接返回可以读写的文件描述符。
poll的实现(<linux/poll.h>):
方法原型:unsigned int (*poll) (struct file *filp, poll_table *wait);
该函数分为两步执行:
在一个或多个可指示poll状态变化的等待队列上调用poll_wait。如果当前没有文件描述符可用来执行I/O,则内核将使进程在传递到该系统调用的所有文件描述符对应的等待队列上等待。
返回一个用来描述操作是否可以立即执行的位掩码。
poll_wait:
void poll_wait(struct file *,wait_queue_head_t *, poll_table *)
位掩码:
POLLIN:如果设备可以无堵塞地读取,就设置该位
POLLRDNORM:如果“通常”的数据已经就绪,可以读取,就设置该位。一个可读设备返回(POLLIN | POLLRDNORM)
POLLOUT:如果设备可以无堵塞地写入,就设置该位
POLLWRNORM:如果“通常”的数据已经就绪,可以写入,就设置该位。一个可读设备返回(POLLOUT | POLLWRNORM)
实例代码(lld3 scull/pipe.c):
down(&dev->sem);
poll_wait(filp, &dev->inq, wait);
poll_wait(filp, &dev->outq,wait);
if (dev->rp != dev->wp)
mask | = POLLIN | POLLRDNORM;
if (spacefree(dev))
mask | = POLLOUT | POLLWRNORM;
up(&dev->sem);
return mask;
2016.04.14