poll的定位
poll也是Linux中内置的一种IO多路复用的接口,它和select的功能上是一样的,都是负责多个fd的IO等待,且一次可以等待多个fd。只是poll针对select的缺点做了些调整和改进。
相较于select的缺点来说,poll改善了如下方面:
1、将输入和输出参数分离,不需要每次都对参数进行重置;
2、解决select等待fd的数量上限问题。
函数用法
函数定义
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
参数说明:
- fds 和 nfds
fds是一个struct pollfd*类型的参数,是一个struct pollfd类型的数组。nfds表示这个数组的长度。同select类似,fds参数也是一个输入输出型参数。
struct pollfd的类型定义如下:
struct pollfd
{
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
其中fd就是对应的文件描述符。events作为输入,表示有哪些请求事件。revents作为输出,表示有哪些事件就绪了。event和events的取值如下:
事件 | 描述 | 是否可作为输入 | 是否可作为输出 |
---|---|---|---|
POLLIN | 数据可读(包括普通数据和优先数据) | 是 | 是 |
POLLRDNORM | 普通数据可读 | 是 | 是 |
POLLRDBAND | 优先级带数据可读(Linux 不支持) | 是 | 是 |
POLLPRI | 高优先级数据可读,比如TCP 带外数据 | 是 | 是 |
POLLOUT | 数据(包括普通数据和优先数据)可写 | 是 | 是 |
POLLWRNORM | 普通数据可写 | 是 | 是 |
POLLWRBAND | 优先级带数据可写 | 是 | 是 |
POLLRDHUP | TCP连接被对方关闭,或者对方关闭了写操作 | 是 | 是 |
POLLERR | 错误 | 否 | 是 |
POLLHUP | 挂起 | 否 | 是 |
POLLNVAL | 文件描述符没被打开 | 否 | 是 |
- timeout
timeout表示poll函数的超时时间,单位是毫秒(ms)。同select的类似,timeout大于0表示最多等待的时间;等于0表示不等待,立即返回;小于0表示阻塞式等待。
- 返回值
大于0,表示等待的多个fd中,已经就绪的fd个数;等于0,表示超时且没有一个就绪;返回-1则表示出错了。
poll的特点
poll的特点:
- 不同于select使用三个位图来表示三个fdset的方式,poll使用一个pollfd的指针实现。
- pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式,接口使用比select更方便。
- poll并没有最大数量限制,其内存是使用链表管理的 (但是数量过大后性能也是会下降的)
poll的缺点 :
- poll中监听的文件描述符数目增多时和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。
- 每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中,资源耗费过大
- 同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长, 其效率也会线性下降。