前两篇文章介绍了select,poll,epoll的基本用法,如今咱们来看看它们的区别和适用场景。html
首先仍是来看常见的select和poll。对于网络编程来讲,通常认为poll比select要高级一些,这主要源于如下几个缘由:编程
固然也不是说select就没有优势:数组
epoll的优势:服务器
1.支持一个进程打开大数目的socket描述符(FD)网络
select 最不能忍受的是一个进程所打开的FD是有必定限制的,由FD_SETSIZE设置,默认值是1024/2048。对于那些须要支持的上万链接数目的IM服务器来讲显然太少了。这时候你一是能够选择修改这个宏而后从新编译内核。不过 epoll则没有这个限制,它所支持的FD上限是最大能够打开文件的数目,这个数字通常远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目能够cat /proc/sys/fs/file-max察看,通常来讲这个数目和系统内存关系很大。socket
2.IO效率不随FD数目增长而线性降低函数
传统的select/poll另外一个致命弱点就是当你拥有一个很大的socket集合,不过因为网络延时,任一时间只有部分的socket是"活跃"的,可是select/poll每次调用都会线性扫描所有的集合,致使效率呈现线性降低。可是epoll不存在这个问题,它只会对"活跃"的socket进行操做---这是由于在内核实现中epoll是根据每一个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数,其余idle状态socket则不会,在这点上,epoll实现了一个"伪"AIO,由于这时候推进力在Linux内核。htm
3.使用mmap加速内核与用户空间的消息传递。blog
这点实际上涉及到epoll的具体实现了。不管是select,poll仍是epoll都须要内核把FD消息通知给用户空间,如何避免没必要要的内存拷贝就很重要,在这点上,epoll是经过内核与用户空间mmap同一块内存实现的。 队列
对于poll来讲须要将用户传入的 pollfd 数组拷贝到内核空间,由于拷贝操做和数组长度相关,时间上这是一个O(n)操做,当事件发生,poll返回将得到的数据传送到用户空间并执行释放内存和剥离等待队列等善后工做,向用户空间拷贝数据与剥离等待队列等操做的的时间复杂度一样是O(n)。
这两天看到一个云风他们那里的bug就是由于使用的开源库中做者使用了非阻塞connect使用select() 来等待超时,可是并未检查FD_SETSIZE,当文件描述符数目大于这个数目以后就会出现内存越界错误,形成coredump。