poll 函数用于检测一组文件描述符(File Descriptor, fd)上的可读可写和出错事件,其函数签名如下:
参数解释:
- fds:指向一个结构体数组的首个元素的指针,每个数组元素都是一个 struct pollfd 结构,用于指定检测某个给定的 fd 的条件;
- nfds:参数 fds 结构体数组的长度,nfds_t 本质上是 unsigned long int,其定义如下:
- timeout:表示 poll 函数的超时时间,单位为毫秒。
返回值和错误代码
成功时,poll()返回结构体中revents域不为0的文件描述符个数;如果在超时前没有任何事件发生,poll()返回0;失败时,poll()返回-1,并设置errno为下列值之一:
- EBADF 一个或多个结构体中指定的文件描述符无效。
- EFAULTfds 指针指向的地址超出进程的地址空间。
- EINTR 请求的事件之前产生一个信号,调用可以重新发起。
- EINVALnfds 参数超出PLIMIT_NOFILE值。
- ENOMEM 可用内存不足,无法完成请求。
struct pollfd 结构体定义如下:
struct pollfd 的 events 字段是由开发者来设置,告诉内核我们关注什么事件,而 revents 字段是 poll 函数返回时内核设置的,用以说明该 fd 发生了什么事件。events 和 revents 一般有如下取值:
事件宏 | 事件描述 | 是否可以作为输入(events) | 是否可以作为输出(revents) |
---|---|---|---|
POLLIN | 数据可读(包括普通数据&优先数据) | 是 | 是 |
POLLOUT | 数据可写(普通数据&优先数据) | 是 | 是 |
POLLRDNORM | 等同于 POLLIN | 是 | 是 |
POLLRDBAND | 优先级带数据可读(一般用于 Linux 系统) | 是 | 是 |
POLLPRI | 高优先级数据可读,例如 TCP 带外数据 | 是 | 是 |
POLLWRNORM | 等同于 POLLOUT | 是 | 是 |
POLLWRBAND | 优先级带数据可写 | 是 | 是 |
POLLRDHUP | TCP连接被对端关闭,或者关闭了写操作,由 GNU 引入 | 是 | 是 |
POPPHUP | 挂起 | 否 | 是 |
POLLERR | 错误 | 否 | 是 |
POLLNVAL | 文件描述符没有打开 | 否 | 是 |
poll 检测一组 fd 上的可读可写和出错事件的概念与前文介绍 select 的事件含义一样,这里就不再赘述。poll 与 select 相比具有如下优点:
- poll 不要求开发者计算最大文件描述符加 1 的大小;
- 相比于 select,poll 在处理大数目的文件描述符的时候速度更快;
- poll 没有最大连接数的限制,原因是它是基于链表来存储的;
- 在调用 poll 函数时,只需要对参数进行一次设置就好了。