poll函数的原型
#include<poll.h>
int poll(struct pollfd *fds,nfds_t nfds, int timeout)
参数说明:
- fds:是一个poll函数监听的结构列表,每一个元素中,都包含了三个部分:文件描述符,监听事件集合,返回事件集合
- nfds:fds数组的长度
- timeout:表示poll函数的超时时间,单位时毫秒
time=-1:这会造成poll永远等待。poll()只有在一个描述符就绪时返回,或者在调用进程捕捉到信号时返回
time=0:这时,测试所有的文件描述符,并且poll()立刻返回,这允许在poll中没有阻塞的情况下找出多个文件描述符的状态
time>0:poll()只会在超时到期时返回,除非一个描述符变成就绪态,如果超时周期到期,poll()返回0,这里也可能因为某个信号中断等待。
//pollfd的结构
struct pollfd
{
int fd;
short events;
short revents;
};
- 不同于select使用三个位图来表示三种fdset,poll使用一个pollfd结构体来表示这些
- 这个结构体就是poll函数提高效率的一个关键
- fd表示 文件描述符,events和revents用来存放实际发生的那些事件的返回
events的取值
revents的取值
返回结果:
- 返回值小于0,表示出错
- 返回值等于0,表示poll等待超时
- 返回值大于0,表示poll由于监听的文件描述符就绪而返回
poll相对于select的优点
- select函数调用完之后,select()函数回清空它的文件描述符fd指定的关心的事(清空位图),而这些位图下次都得遍历来重新定义,也就是又遍历一遍fd集合
- poll函数的fds是一个struct pollfd结构类型的数组,每当系统调用poll函数之后,不会清空这个数组,操作起来比较方便。
- 特别是socket比较多的情况下,使用poll一定程度上可以提高效率
- select()适用于只检测一个socket描述符的情况
- poll()函数适用于大量的socket描述符的情况
poll的优点
- 不同于select使用三个位图开表示桑fdset,poll使用一个pollfd的指针实现
- pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式,接口比select方便
- poll并没有最大数量的限制(但是数量过大后性能也会下降)
poll的缺点:
poll中监听的文件描述符增多时
- 和select一样,poll返回后,需要轮询pollfd来获取就绪的文件描述符
- 每次调用poll都需要把大量的pollfd结构从用户态拷贝至内核中
- 同时连接的大量客户端在同一时刻可能只有很少的处于就绪状态,因此随着监视的秒护肤数量增长 ,其效率会线性下降。
select和poll都需要在返回之后,通过遍历文件描述符获取已经就绪的socket,如果有人向恶意攻击,让服务器短时间内产生大量的客户,因为每次poll()返回后,都要遍历文件描述符来获取已就绪的socket,只要用户足够多,让你每次遍历时都拥有死循环的遍历长度,这时候的poll和谈性能