先对比一下select和poll
(1)poll不要求开发者在计算最大文件描述符时进行+1的操作
(2)poll在应付大数目的文件描述符的时候速度更快,因为对于select来说内核需要检查大量描述符对应的fd_set中的每一个比特位
(3)select可以监控的文件描述数目是固定的,相对来说较少(1024/2048)。
如果需要监控数值比较大的文件描述符,或者是分布的很稀疏的较少的描述符,效率也会很低。
而对于poll函数来说,就可以创建特定大小的数组来保存监控的描述符,而不受文件描述符值大小的影响,而且poll可以监控的文件数目大于select
(4)对于select来说,所监控的fd_set在select返回之后会发生变化, 所以在下一次进入select之前都需要初始化需要监控的fd_set
poll函数将监控的输入和输出时间分开,允许被监控的文件数组被复用而不需要重新初始化
select的优点如下
(1)select的可移植性好,在某些UNIX系统上不支持Poll
(2)slect对于超时值提供了更好的精度,而poll的精度较差
epoll优点如下:
(1)支持一个进程打开大数目的socket描述符
select最不能忍受的是一个进程所打开的FD友一定的限制,因为FD_SETSIZE的默认值为1024/2048
对于那些需要支持上完链接数目的IM服务器来说显然太笑了,这时候可以选择修改这个宏然后重新编译内核
不过epoll没有这个限制,它所支持的FD上限是最大可以打开的数目,这个数字远大于2048。比如在1GB内存的空间中这个数字为10WW
(2)IO效率不随FD数组增加而线性下降
select和poll都有一个致命的弱点就是因为网络延迟的问题,大量的socket在这这时候只会有一小部分是活跃的,然而select和poll
每次调用都会线性扫描全部的集合,这时候就导致效率的下降。但是epoll不存在这个其问题,它只会对活跃的socket进行操作
则是因为在内核中实现epoll是根据每个fd上面的callback函数实现的。name只有活跃的socket才会主动调用callback
其他处于idle形态的socket则不会
(3)使用mmap加速内核与用户空间的消息传递
无论是epoll还是select、poll都需要内核将fd信息通知给用户空间,如何避免不必要的内存拷贝就显得尤为重要
epoll是通过内核与用户空间的mmap处于同一内存空间实现的
对于poll来说用户传入pollfd数组拷贝到内和空间,因为拷贝操作和数组长度,时间上看这是O(n)操作
当事件发生后,poll将获得的数据传送到用户空间。并执行释放内存和剥离等待队列等工作,向用户空间拷贝数据
与剥离等待队列等操作的世界都时候O(n)