3、epoll基本概念

1、基于概念

    epoll是一种机制,来处理大量并发连接时事件的读写顺序。

linux的网络编程中,很长的时间都在使用select来做事件触发2.5.X内核后,引入epoll

epoll是Linux内核为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。

因为它不会复用文件描述符集合来传递结果而迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了epoll的除了提供select/poll那种IO事件的电平触发Level Triggered外,还提供了边沿触发Edge Triggered,这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

linux/posix_types.h头文件有这样的声明:

#define __FD_SETSIZE    1024

表示select最多同时监听1024fd,当然,可以通过修改头文件再重编译内核来扩大这个数目。

epoll所支持的FD上限是最大可以打开文件的数目,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看。

2、效率

    select/poll致命弱点是当拥有个很大的socket集合,不过由于网络延时,任一时间只有部分的socket是“活跃”的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对“活跃”的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有“活跃”的socket才会主动的去调用 callback函数,其他idle状态socket则不会,在这点上,epoll实现了一个“伪”AIO,因为这时候推动力在os内核。在一些 benchmark中,如果所有的socket基本上都是活跃的---比如一个高速LAN环境,epoll并不比select/poll有什么效率,相反,如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。

3、工作模式

    LT(level triggered)是缺省的工作方式,并且同时支持blockno-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表。

ET(edge-triggered是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,继续发送数据,将导致另一个就绪状态;把缓存中的数据全部read完;或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK/EAGAIN 错误等三种情况)。但是请注意,如果一直不对这个fdIO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),也就是说:每次连续的数据流只通知一次,不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认。

总结一下:

ET模式仅当状态发生变化的时候才获得通知,这里所谓的状态的变化并不包括缓冲区中还有未处理的数据,也就是说,如果要采用ET模式,需要一直read/write直到出错为止,很多人反映为什么采用ET模式只接收了一部分数据就再也得不到通知了,大多因为这样;而LT模式是只要有数据 没有处理就会一直通知下去的。

原文地址:https://www.cnblogs.com/mydomain/p/2163272.html