poll与select相似,但是select有一个致命缺点就是可以监视的描述符有限,最多1024个,所以poll解决了这个问题,没有了最大文件描述符的限制,但是他们俩还存在一个问题就是文件描述符的数组整个的存在于用户空间和内核空间中,fd很多时,就会增大开销,所以epoll就解决了这个问题,只有就绪的文件描述符才会发出类似信号一样的通知,这个后面会讲到
poll函数原型,需要#include <poll.h>
int poll(struct pollfd *fdset, unsigned int nfds, int timeout);
struct pollfd的定义:
struct pollfd
{
int fd; //文件描述符
short events; //等待的事件
short revents; //实际发生了的事件
};
每个结构体只能表示一个文件描述符(类似于句柄,用来标识某个资源),根据函数原型可以看出,参数为结构体指针,所以理论上可以监视无限个文件描述符,如果存储够的话。每个结构体的events是监视该文件描述符的事件掩码(也就是一个短整数),我们设置,revents是文件描述符的操作结果事件掩码,需要内核返回时设置这个
事件如下:
POLLIN 有数据可读。
POLLRDNORM 有普通数据可读。
POLLRDBAND 有优先数据可读。
POLLPRI 有紧迫数据可读。
POLLOUT 写数据不会导致阻塞。
POLLWRNORM 写普通数据不会导致阻塞。
POLLWRBAND 写优先数据不会导致阻塞。
POLLMSGSIGPOLL 消息可用。
此外,revents域中还可能返回下列事件:这些总是在内核设置,在events中无意义
POLLER 指定的文件描述符发生错误。
POLLHUP 指定的文件描述符挂起事件。
POLLNVAL 指定的文件描述符非法。
poll()不需要像select()一样显式地请求异常情况报告
比如events中的pollin被设置,poll返回时,如果revents的pollin被设置,则表示该文件描述符可以被读取而不被阻塞,这些事件可以同时被设置
timeout参数:指定等待的毫秒数,而无论IO是否准备好
timeout为负数时:代表无限等待直到某一指定事件发生
为0时:poll调用立即返回并且列出准备好IO的文件描述符,但是不等待其它事件
返回值
成功时:返回结构体链中revents不为0的文件描述符个数。
超时前没有任何事件发生返回0
失败时返回-1,并且设置errno为下列常量中的一个:
EBADF 一个或多个结构体中指定的文件描述符无效。
EFAULTfds 指针指向的地址超出进程的地址空间。
EINTR 请求的事件之前产生一个信号,调用可以重新发起。
EINVALnfds 参数超出PLIMIT_NOFILE值。
ENOMEM 可用内存不足,无法完成请求。