events可以表示合法的事件如下:
事件描述POLLIN有数据可读POLLRDNORM有普通数据可读POLLRDBAND有优先数据可读。POLLPRI有紧迫数据可读。POLLOUT写数据不会导致阻塞POLLWRNORM写普通数据不会导致阻塞POLLWRBAND写优先数据不会导致阻塞POLLMSGSIGPOLL消息可用。
除了上面,revents域中还可能返回下列事件:
事件描述POLLER指定的文件描述符发生错误POLLHUP指定的文件描述符挂起事件POLLNVAL指定的文件描述符非法
这些事件在events域中无意义,因为它们在合适的时候总是会从revents中返回。
其实这里我们就可以看到poll函数较与select函数的优点在哪里,因为如果你是select函数,在调用完之后, select() 函数会清空 它 的文件描述符fd指 定的关心的事件(也就是清空位图),这些在下次都得遍历来重新定义.也 就是又遍历 一遍fd集合. POLL函数: fds: 是一个struct pollfd结构类型的数 组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系 统不会清空这 个数组, 操作起来比较方便;特别是对于socket连接比较多的 情况下,在一定程度上可以提高处理的效 率;这一点与select()函数 不同,调用 select()函数之后,select()函数会清空它所检测的socket描述符集 合,导致 每 次调用select()之前都必须把socket描 述符重新加 入到待检测的集合中;因此,select()函数适合于只检测一个 socket描述符的情况,而 poll()函数适合于大量socket描 述符的情况; nfds nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;
timeout:
timeout 为 -1 这会造成 poll 永远等待。poll() 只有在一个描述符就绪时返回,或者在调用进程捕捉到信号时返回(在这里,poll 返回 -1),并 且 设置 errno 值 为 EINTR 。-1 可以用宏定义常量 INFTIM 来代替(在 pth.h 中有定义) 。 timeout 等于0 在这种情况下,测试所有的描述符,并且 poll() 立刻返回。这允许在 poll 中没有阻塞的情况下找出多个文件描述 符的状态。 time > 0 这将以毫秒为单位指定 timeout 的超时周期。poll() 只有在超时到期时返回,除非一个描述符变为就绪,在这种情 况下,它立刻 返回 如果超时周期 到 齐,poll() 返回 0。这里也可能会因为某个信号而中断该等待。和 select 一样, 文件描述符是否阻塞对 poll 是否 阻塞没有任何影响. 其实我们应该已经看出来poll服务器的优势了吧~ 它首先相对于select服务来说,提升了性能它用 pollfd结构体,防 止了程序里面 嵌套的各种各样繁琐 循环,以及呢select服务器它最大可以同时监视的文件描述符是一个定长的, 而poll 改变了这个因为它是由用 户输入的长度,你输入多少那么我就给你 多少个pollfd结构体,这样有问题也不关我函数的 事情, 使用户自己使用出现问题. 是不 是感觉poll完美了?无敌了? 其实我们应该冷静下来,再想 想为什么当前基 本都 在使用最广泛 的是epoll服务器而不是poll? 如果 poll这么无坚不摧的他为什么会被epoll取代? 思考一下 poll服务器 在怎么样的 应用场景下,就会出现问题? select和poll都需要在返回后,通过遍历文件描述符来获取已经就绪的socket,这样想如果你可以表示的文件描 述符 超级超级的 多 ,这时候有人攻 击你,让你的服务器短时间内产生大量的用户,因为每次返回后都需要遍历文件 描述符来 获取已经就绪的 socket, 这时候如果用户足够的多,别人 给你创建了骚起来创建用户,让你返回每次遍历 的时候拥有接 近死循环的遍历长度,这 时候poll 服务器何谈性能而言? 其实如果不解决通过遍历查 找就绪的文件描 述符这种形式你的 服务器其实就是相对不安全,而且 就算是没有 人攻击你,比如像双11这种购物节,如果马云使用 的poll服务器那 么, 服务器可能骚起来挂,马云心态就该崩了. 所以呢,因为poll也是在返回后,通过遍历文件描述符来获取已经就绪的socket,事实上,在连接的大量的客户端 在某一时刻他 们之 间就绪的客户 端通常不会很多,因为随着文件描述符的增多,poll的效率也会成线性下降.这个时 候就出现了poll的升级版本 epoll, 它真的可以完美解决掉一切 select和poll所遇到的问题,而且技术很成熟很稳定 效率很高,当今拥有最好的I/O就绪通知 方法,在 下一个博客我会详细的说明他底层的实现原 理.