我们目前的网络模型大都是epoll的,因为epoll模型会比select模型性能高很多, 尤其在大连接数的情况下,作为后台开发人员需要理解其中的原因。
select/epoll的特点
select的特点:
select 选择句柄的时候,是遍历所有句柄,也就是说句柄有事件响应时,select需要遍历所有句柄才能获取到哪些句柄有事件通知,因此效率是非常低。但是如果连接很少的情况下, select和epoll的LT触发模式相比, 性能上差别不大。
这里要多说一句,select支持的句柄数是有限制的,
同时只支持1024个,这个是句柄集合限制的,如果超过这个限制,很可能导致溢出,而且非常不容易发现问题, TAF就出现过这个问题,
调试了n天,才发现:)当然可以通过修改linux的socket内核调整这个参数。
epoll的特点:
epoll对于句柄事件的选择不是遍历的,是事件响应的,就是句柄上事件来就马上选择出来,不需要遍历整个句柄链表,因此效率非常高,内核将句柄用红黑树保存的。
对于epoll而言还有ET和LT的区别,LT表示水平触发,ET表示边缘触发,两者在性能以及代码实现上差别也是非常大的。
epoll的LT和ET的区别
LT:水平触发,
效率会低于ET触发,尤其在大并发,大流量的情况下。但是LT对代码编写要求比较低,不容易出现问题。LT模式服务编写上的表现是:只要有数据没有被获取,内核就不断通知你,因此不用担心事件丢失的情况。
ET:边缘触发,
效率非常高,在并发,大流量的情况下,会比LT少很多epoll的系统调用,因此效率高。但是对编程要求高,需要细致的处理每个请求,否则容易发生丢失事件的情况。
下面举一个列子来说明LT和ET的区别(都是非阻塞模式,阻塞就不说了,效率太低):
采用LT模式下, 如果accept调用有返回就可以马上建立当前这个连接了,再epoll_wait等待下次通知,和select一样。
但是对于ET而言,如果accpet调用有返回,除了建立当前这个连接外,不能马上就epoll_wait还需要继续循环accpet,直到返回-1,且errno==EAGAIN,TAF里面的示例代码:
if(ev.events & EPOLLIN)
{
do
{
struct sockaddr_in stSockAddr;
socklen_t iSockAddrSize = sizeof(sockaddr_in);
TC_Socket cs;
cs.setOwner(false);
//接收连接
TC_Socket s;
s.init(fd, false, AF_INET);
int iRetCode = s.accept(cs, (struct sockaddr *) &stSockAddr, iSockAddrSize);
if (iRetCode > 0)
{
...建立连接
}
else
{
//直到发生EAGAIN才不继续accept
if(errno == EAGAIN)
{
break;
}
}
}while(true);
}
同样,recv/send等函数, 都需要到errno==EAGAIN
从本质上讲:与LT相比,ET模型是通过减少系统调用来达到提高并行效率的。
epoll ET详解
ET模型的逻辑:内核的读buffer有内核态主动变化时,内核会通知你,
无需再去mod。写事件是给用户使用的,最开始add之后,内核都不会通知你了,你可以强制写数据(直到EAGAIN或者实际字节数小于
需要写的字节数),当然你可以主动mod OUT,此时如果句柄可以写了(send buffer有空间),内核就通知你。
这里内核态主动的意思是:内核从网络接收了数据放入了读buffer(会通知用户IN事件,即用户可以recv数据)
并且这种通知只会通知一次,如果这次处理(recv)没有到刚才说的两种情况(EAGIN或者实际字节数小于 需要读写的字节数),则该事件会被丢弃,直到下次buffer发生变化。
与LT的差别就在这里体现,LT在这种情况下,事件不会丢弃,而是只要读buffer里面有数据可以让用户读,则不断的通知你。
另外对于ET而言,当然也不一定非send/recv到前面所述的结束条件才结束,用户可以自己随时控制,即用户可以在自己认为合适的时候去设置IN和OUT事件:
1 如果用户主动epoll_mod OUT事件,此时只要该句柄可以发送数据(发送buffer不满),则epoll
_wait就会响应(有时候采用该机制通知epoll_wai醒过来)。
2 如果用户主动epoll_mod IN事件,只要该句柄还有数据可以读,则epoll_wait会响应。
这种逻辑在普通的服务里面都不需要,可能在某些特殊的情况需要。 但是请注意,如果每次调用的时候都去epoll mod将显著降低效率,已经吃过几次亏了!
因此采用et写服务框架的时候,最简单的处理就是:
建立连接的时候epoll_add IN和OUT事件, 后面就不需要管了
每次read/write的时候,到两种情况下结束:
1 发生EAGAIN
2 read/write的实际字节数小于 需要读写的字节数
对于第二点需要注意两点:
A:如果是UDP服务,处理就不完全是这样,必须要recv到发生EAGAIN为止,否则就丢失事件了
因为UDP和TCP不同,是有边界的,每次接收一定是一个完整的UDP包,当然recv的buffer需要至少大于一个UDP包的大小
随便再说一下,一个UDP包到底应该多大?
对于internet,由于MTU的限制,UDP包的大小不要超过576个字节,否则容易被分包,对于公司的IDC环境,建议不要超过1472,否则也比较容易分包。
B 如果发送方发送完数据以后,就close连接,这个时候如果recv到数据是实际字节数小于读写字节数,根据开始所述就认为到EAGIN了从而直接返回,等待下一次事件,这样是有问题的,close事件丢失了!
因此如果依赖这种关闭逻辑的服务,必须接收数据到EAGIN为止,例如lb。
分享到:
相关推荐
【epoll 使用详解】 在 Linux 网络编程中,epoll 是一种高效、可扩展的 I/O 事件通知机制,用于替代传统的 select 和 poll。epoll 的主要优点在于其性能不受监听文件描述符(fd)数量的影响,这是因为epoll 采用了...
`epoll`提供了两种主要的工作模式: - **Level Triggered (LT)**:水平触发。只要文件描述符上有事件,就会一直触发。 - **Edge Triggered (ET)**:边缘触发。只有当事件状态从无变有时才会触发,适用于性能敏感的...
《Epoll模型详解》 Epoll是Linux内核提供的一种高效、可扩展的I/O事件通知机制,尤其在处理大量并发连接时表现出显著优势。它替代了传统的select和poll方法,解决了这些方法在处理大量文件描述符(fd)时效率低下的...
Epoll有两种工作模式:Edge Triggered(ET)和Level Triggered(LT)。 - Edge Triggered(ET)模式:只有当数据真正到达时,Epoll才会触发事件。例如,在管道读取的例子中,如果在epoll_wait返回后仅读取部分数据,ET...
`linux下的Tcp服务器,采用的是Epoll模式,deamon程序,适合大家.rar`和`.tar`文件提供了实际的Epoll TCP服务器示例,而`linux下用epoll实现的udp服务器例子,很精简和实用.rar`则展示了Epoll在UDP服务器中的应用。...
- **EPOLLET**:边缘触发(Edge Triggered)模式,当文件描述符状态从非就绪变为就绪时,epoll_wait()才会返回。相比默认的水平触发(Level Triggered),边缘触发可以减少不必要的唤醒,提高效率。 - **EPOLLERR**...
epoll提供了两种工作模式:Edge Triggered(ET)和Level Triggered(LT)。ET模式只在数据真正到达时触发,即只有当新的数据到来才会再次触发读事件。而LT模式只要数据可用就会触发,即使之前的数据还没有被完全读取。ET...
**epoll详解** epoll(边缘触发)是对传统select和poll(水平触发)的改进,克服了它们在处理大量文件描述符时的性能瓶颈。epoll通过内核与用户空间的数据共享来提高效率,当文件描述符上有事件发生时,内核会将相关...
epoll的工作流程分为三步: 1. 调用epoll_create创建epoll对象。 2. 使用epoll_ctl向epoll对象中添加或删除需要监控的文件描述符。 3. 调用epoll_wait等待并收集发生的事件。 epoll_ctl允许添加、修改或删除文件...
2. **epoll接口详解** - `epoll_create`: 创建一个`epoll`实例,返回一个文件描述符。 - `epoll_ctl`: 添加、修改或删除监控的文件描述符,操作包括`EPOLL_CTL_ADD`、`EPOLL_CTL_MOD`和`EPOLL_CTL_DEL`。 - `...
**epoll服务器详解** 在Linux系统中,epoll是一种I/O多路复用技术,用于高效地处理大量的并发连接。它是poll和select方法的增强版本,尤其适合高性能、高并发的网络服务。本文将深入探讨epoll的工作原理、优势以及...
`epoll`采用“事件驱动”模型,可以实现“水平触发”和“边缘触发”两种模式,且支持批量操作,性能更优。基本接口包括: - `epoll_create`: 创建一个epoll实例。 - `epoll_ctl`: 添加、修改或删除文件描述符到...
**epoll底层详解** 在Linux系统中,I/O模型的管理是系统性能的关键因素之一,尤其是在高并发的网络服务中。epoll是Linux提供的一种高效、可扩展的I/O事件通知机制,它优化了传统的select和poll方法,适用于大规模...
#### 五、epoll详解 - **概述**:epoll是Linux内核为提高文件描述符监测的效率而提出的I/O多路复用技术。与select和poll相比,epoll提供了更高的灵活性和效率,尤其适合处理大量并发连接的场景。 - **核心特点**:...
**Epoll 套接字详解** 在计算机网络编程中,多路复用技术是处理大量并发连接的关键。其中,Epoll(Event Poll)是Linux系统提供的一种高效、灵活的I/O多路复用机制,尤其适用于高并发的服务器场景。本教程将深入...
### Proactor模式&Reactor模式详解 #### 一、引言 在服务器端编程领域,构建高效的输入/输出(I/O)模型对于提高程序性能至关重要。根据数据传输方式的不同,通常将I/O模型分为四类:同步阻塞I/O、同步非阻塞I/O、I...
#### 四、Epoll 的两种工作模式详解 epoll 支持两种主要的工作模式:水平触发(Level Triggered, LT)和边缘触发(Edge Triggered, ET)。 1. **水平触发(LT)模式** - 这是 epoll 的默认工作模式,它支持阻塞和...