1、select的些许缺点
回忆一下 select接口
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
select需要我们指定文件描述符的最大值,然后取[0,nfds)这个范围内的值查看是在集合readfds,writefds或execptfds中,也就是说这个范围内存在一些不是我们感兴趣的文件描述符,cpu做了一些无用功,poll对她进行了改进,下面就看看poll是怎么做的。
2、poll接口
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
跟select不同的是,poll不再告知内核一个范围,而是通过struct pollfd结构体数组精确的告知内核用户关心哪些文件描述符(流)。参数nfds指示结构体数组的大小。timeout表示程序员的忍耐度,有三种取值:
- 0,poll函数不阻塞
- 整数,阻塞timeout时间
- 负数,无限阻塞
下面来看一下struct pollfd结构体,以及其中的事件有哪些取值,及其含义
struct pollfd {
int fd; /* an open file file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
- fd属性表示一个打开的文件描述符
- events属性是一个输入参数,通过bit mask的方式描述程序感兴趣的事件(读、写)
- revents属性是一个传出参数,同样式通过bit mask的方式描述发生的事件,这个属性的值是由内核设置的。revents的值可能是events属性的值,也可能是POLLERR,POLLHUP,POLLNVAL的一个或多个,POLLERR,POLLHUP,POLLNVAL在events属性中是没有意义的。
events 和 revents能够设置的值都定义在<poll.h>头中,有以下几种可能
- POLLIN ,读事件
- POLLPRI,读事件,但表示紧急数据,例如tcp socket的带外数据
- POLLRDNORM , 读事件,表示有普通数据可读
- POLLRDBAND , 读事件,表示有优先数据可读
- POLLOUT,写事件
- POLLWRNORM , 写事件,表示有普通数据可写
- POLLWRBAND , 写事件,表示有优先数据可写
- POLLRDHUP (since Linux 2.6.17),Stream socket的一端关闭了连接(注意是stream socket,我们知道还有raw socket,dgram socket),或者是写端关闭了连接,如果要使用这个事件,必须定义_GNU_SOURCE 宏。这个事件可以用来判断链路是否发生异常(当然更通用的方法是使用心跳机制)。要使用这个事件,得这样包含头文件:
#define _GNU_SOURCE
#include <poll.h> - POLLERR,仅用于内核设置传出参数revents,表示设备发生错误
- POLLHUP,仅用于内核设置传出参数revents,表示设备被挂起,如果poll监听的fd是socket,表示这个socket并没有在网络上建立连接,比如说只调用了socket()函数,但是没有进行connect。
- POLLNVAL,仅用于内核设置传出参数revents,表示非法请求文件描述符fd没有打开
poll函数返回值,有三种可能
- positive number,表示struct pollfd结构体数组中有多少个非0的revents,换句话说,就是这一次调用poll发生哪些事件。
- 0,表示timeout到时,并且没有文件描述符准备好
- -1,内部发生了错误,errno将会被设置
当poll返回值为-1时,表示poll出错,errno将被设置,errno的取值有4种可能
- EFAULT ,参数struct pollfd结构体数组不在用户地址空间,比如传入的参数nfds比实际的数组要大。
- EINTR ,被信号中断.
- EINVAL , nfds 超出了RLIMIT_NOFILE值.
- ENOMEM ,内核没有足够的内存装载struct pollfd结构体数组
3、poll与select参数对比
使用poll()和select()不一样,你不需要显式地请求异常情况报告。
POLLIN | POLLPRI等价于select()的读事件,POLLOUT |POLLWRBAND等价于select()的写事件。POLLIN等价于POLLRDNORM |POLLRDBAND,而POLLOUT则等价于POLLWRNORM。
4、poll原理
poll的功能和select的功能一样,只不过是参数稍微不同,poll的底层原理也和select差不多,就不多说了,I/O多路复用之select
来源:https://www.cnblogs.com/zengzy/p/5115679.html