POLL机制
poll机制的底层实现原理:基于等待队列来实现。
poll()函数,poll()函数底层函数接口有一个对应的函数指针。当调用poll()函数的时候,会找到对应的file_operations的成员变量poll,最终会调用poll成员变量指向的函数指针。
同步阻塞IO和异步阻塞IO
同步阻塞IO
应用层调用一个 read / write 对一个文件进行读写操作时, read / write可能使当前的进程或线程进入一个休眠态(进程 / 线程阻塞在一个文件的读写操作上),陷入休眠态的进程 / 线程只能通过对应的文件设备驱动唤醒自己。
异步阻塞IO
在应用层调用poll()函数时,poll()函数会对多个文件进行轮询操作,去查看每一个文件是否有特定的事件。若所有文件都没有发生特定的事件,那么poll()函数会阻塞当前进程 / 线程。
poll()函数文件操作涉及多个文件的轮询,所以poll()函数引起的进程 / 线程休眠,可以会被多个设备驱动唤醒。
多个文件对应多个设备驱动。阻塞在多个文件的轮询操作上(poll),可以被多个设备驱动唤醒。
文件I/O事件类型
事件类型:可读、可写、异常...
poll()函数的目的是查询每个文件的I/O事件,没查到就会引起休眠。这些事件是由设备驱动产生,产生后会唤醒由poll()函数导致的进程 / 线程休眠,poll()函数也能把发生的事件返回给用户空间。
poll()函数
头文件
#include <poll.h>
函数定义
/** 监视多个文件描述符的指定事件(注意:不是所有事件)* 事件发生时(设备驱动唤醒poll函数导致休眠的进程/线程),把发生的具体事件通知给用户程序* fds:数组类型详见下* nfds:pollfd数组的元素个数,要监控的文件描述符数量* timeout:超时时间(ms),不希望进程线程一直休眠在poll函数里*/
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
/** 返回值:* 成功:发生事件的文件数量,超时返回0* 失败:-1*/struct pollfd
{int fd; // 要监视的文件描述符short events; // 指定要监视的请求事件类型,通过设置一系列的宏来描述 short revents; // 返回的事件类型,内核设置具体的返回事件,记录实际发生的事件
};
events监视的事件:
POLLIN:系统内核通知应用层指定数据已经准备好,读数据不会被阻塞
POLLPRI:有紧急的数据需要被读取
POLLOUT:系统内核通知应用层IO缓冲区已经准备好,写数据不会被阻塞
POLLERR:指定的文件描述符发生错误,必须先解决错误才能对文件做其他的处理
POLLNVAL:无效的请求
...
实验环节
app.c文件
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <poll.h> int main(int argc, char *argv[])
{struct pollfd fds = {0};fds.fd = 0; //标准输入fds.events = POLLIN;int ret = poll(&fds, 1, 5000); //监视1个数组,5s超时if(ret == -1){printf("poll error!\n");}else if(ret){printf("data is ready!\n");}else if(ret == 0){printf("time out!\n");}return 0;
}
执行过程
gcc app.c -o App
sudo ./App(回车等待5s)
sudo ./App &
cat
2