epoll的ET和LT模式

epollLTET模式 epoll 对文件描述符有两种操作模式LT(Level Trigger,电平触发)模式 ET(EdgeTrigger,边沿触发)模式LT 模式是默认的工作模式。当往 epoll 内核事件表中注册一个文件描述符上的 EPOLLET 事件时,epoll 将以高效的 ET 模式 来操作该文件描述符。对于 LT 模式操作的文件描述符,当 epoll_wait 检测到其上有事件发生并将此事件通知应用程序后,应用程序可以不立即处理该事件。 阅读详情

http://www.kuqin.com/linux/20120912/330528.html

在一个非阻塞的socket上调用read/write函数, 返回EAGAIN或者EWOULDBLOCK(注: EAGAIN就是EWOULDBLOCK)
从字面上看, 意思是:EAGAIN: 再试一次,EWOULDBLOCK: 如果这是一个阻塞socket, 操作将被block,perror输出: Resource temporarily unavailable

总结:
这个错误表示资源暂时不够,能read时,读缓冲区没有数据,或者write时,写缓冲区满了。遇到这种情况,如果是阻塞socket,read/write就要阻塞掉。而如果是非阻塞socket,read/write立即返回-1, 同时errno设置为EAGAIN。
所以,对于阻塞socket,read/write返回-1代表网络出错了。但对于非阻塞socket,read/write返回-1不一定网络真的出错了。可能是Resource temporarily unavailable。这时你应该再试,直到Resource available。

综上,对于non-blocking的socket,正确的读写操作为:
读:忽略掉errno = EAGAIN的错误,下次继续读
写:忽略掉errno = EAGAIN的错误,下次继续写

对于select和epoll的LT模式,这种读写方式是没有问题的。但对于epoll的ET模式,这种方式还有漏洞。

epoll的两种模式LT和ET
二者的差异在于level-trigger模式下只要某个socket处于readable/writable状态,无论什么时候进行epoll_wait都会返回该socket;而edge-trigger模式下只有某个socket从unreadable变为readable或从unwritable变为writable时,epoll_wait才会返回该socket。

所以,在epoll的ET模式下,正确的读写方式为:
读:只要可读,就一直读,直到返回0,或者 errno = EAGAIN
写:只要可写,就一直写,直到数据发送完,或者 errno = EAGAIN

正确的读

 
n = 0;
while ((nread = read(fd, buf + n, BUFSIZ-1)) > 0) {
n += nread;
}
if (nread == -1 && errno != EAGAIN) {
perror("read error");
}

正确的写

 
int nwrite, data_size = strlen(buf);
n = data_size;
while (n > 0) {
nwrite = write(fd, buf + data_size - n, n);
if (nwrite < n) {
if (nwrite == -1 && errno != EAGAIN) {
perror("write error");
}
break;
}
n -= nwrite;
}

正确的accept,accept 要考虑 2 个问题
(1) 阻塞模式 accept 存在的问题
考虑这种情况:TCP连接被客户端夭折,即在服务器调用accept之前,客户端主动发送RST终止连接,导致刚刚建立的连接从就绪队列中移出,如果套接口被设置成阻塞模式,服务器就会一直阻塞在accept调用上,直到其他某个客户建立一个新的连接为止。但是在此期间,服务器单纯地阻塞在accept调用上,就绪队列中的其他描述符都得不到处理。

解决办法是把监听套接口设置为非阻塞,当客户在服务器调用accept之前中止某个连接时,accept调用可以立即返回-1,这时源自Berkeley的实现会在内核中处理该事件,并不会将该事件通知给epool,而其他实现把errno设置为ECONNABORTED或者EPROTO错误,我们应该忽略这两个错误。

(2)ET模式下accept存在的问题
考虑这种情况:多个连接同时到达,服务器的TCP就绪队列瞬间积累多个就绪连接,由于是边缘触发模式,epoll只会通知一次,accept只处理一个连接,导致TCP就绪队列中剩下的连接都得不到处理。

解决办法是用while循环抱住accept调用,处理完TCP就绪队列中的所有连接后再退出循环。如何知道是否处理完就绪队列中的所有连接呢?accept返回-1并且errno设置为EAGAIN就表示所有连接都处理完。

综合以上两种情况,服务器应该使用非阻塞地accept,accept在ET模式下的正确使用方式为:

 
while ((conn_sock = accept(listenfd,(struct sockaddr *) &remote, (size_t *)&addrlen)) > 0) {
handle_client(conn_sock);
}
if (conn_sock == -1) {
if (errno != EAGAIN && errno != ECONNABORTED && errno != EPROTO && errno != EINTR)
perror("accept");
}

一道腾讯后台开发的面试题
使用Linuxepoll模型,水平触发模式;当socket可写时,会不停的触发socket可写的事件,如何处理?

第一种最普遍的方式:
需要向socket写数据的时候才把socket加入epoll,等待可写事件。
接受到可写事件后,调用write或者send发送数据。
当所有数据都写完后,把socket移出epoll。

这种方式的缺点是,即使发送很少的数据,也要把socket加入epoll,写完后在移出epoll,有一定操作代价。

一种改进的方式:
开始不把socket加入epoll,需要向socket写数据的时候,直接调用write或者send发送数据。如果返回EAGAIN,把socket加入epoll,在epoll的驱动下写数据,全部数据发送完毕后,再移出epoll。

这种方式的优点是:数据不多的时候可以避免epoll的事件处理,提高效率。

CSP历年真题201503-1-图像旋转(C/C++) 一、问题描述 旋转是图像处理的基本操作,在这个问题中,你需要将一个图像逆时针旋转90度。 计算机中的图像表示可以用一个矩阵来表示,为了旋转一个图像,只需要将对应的矩阵旋转即可。 输入格式 二、输入格式 输入的第一行包含两个整数n, m,分别表示图像矩阵的行数列数。 接下来n行每行包含m个整数,表示输入的图像。 三、输出格式 输出m行,每行包含n个整数,表示原始矩阵逆时针旋转90度后的矩阵。 四、... 阅读详情

相关推荐

105. replace( )函数

【目录】

weixin_63986098的博客 1万+

我读过的最好的epoll讲解--转自”知乎“

作者:蓝形参,Geek 伪技术宅    首先我们来定义流的概念,一个流可以是文件,socket,pipe等等可以进行I/O操作的内核对象。    不管是文件,还是套接字,还是管道,我们都可以把他们看作流。    之后我们来讨论I/O的操作,通过read,我们可以从流中读入数据;通过write,我们可以往流写入数据。现在假定一个情形,我们需要从流中读数据,但是流中还没有数据,(典型的例子为,客户端要...

weixin_34015336的博客 9556

FusionCompute 6.5.1_CNA.iso

FusionCompute 6.5.1_CNA.iso镜像

EpollLTET模式下的读写方式以及EPOLL实例

http://blog.csdn.net/xitong2012/article/details/7076376 #include #include #include #include #include #include #include #include #include #include #include #include #include

bytxl的专栏 1334

epoll

生活中的例子:区分selectepoll 以一个生活中的例子来解释. 假设你在大学中读书,要等待一个朋友来访,而这个朋友只知道你在A号楼,但是不知道你具体住在哪里,于是你们约好了在A号楼门口见面. 如果你使用的阻塞IO模型来处理这个问题,那么你就只能一直守候在A号楼门口等待朋友的到来,在这段时间里你不能做别的事情,不难知道,这种方式的效率是低下的. 进一步解释selectepoll模型的

yuanchunsi的博客 936

epoll读写事件触发的条件

先上个人理解: EPOLLIN(读事件) EPOLLOUT(写事件) 以下触发条件只要满足一点即可。 LT模式EPOLLIN触发条件: 处于可读状态。 从不可读状态变为可读状态。 EPOLLOUT触发条件: 处于可写状态。 从不可写状态变为可写状态。 说白了,LT模式就是能读的时候就可读,能写的时候就可写。这并不是废话。 什么叫可读状态?什么叫不可读状态? 一个水杯里有水...

回头太难 8172

epoll详解

一、从网卡接收数据说起 下图是一个典型的计算机结构图,计算机由CPU、存储器(内存)、网络接口等部件组成。了解epoll本质的第一步,要从硬件的角度看计算机怎样接收网络数据。 计算机结构图(图片来源:linux内核完全注释之微型计算机组成结构) 下图展示了网卡接收数据的过程。在①阶段,网卡收到网线传来的数据;经过②阶段的硬件电路的传输;最终将数据写入到内存中的某个地址上(③阶段)。这个过程涉及到DMA传输、IO通路选择等硬件有关的知识,但我们只需知道:网卡会把接收到的数据写入内存。 网卡接收

haogenmin的博客 1万+

epoll中的ETLT模式区别

epoll中的ETLT模式一、水平触发(LT边沿触发(ET)二、例子1.例子:水平触发(LT)2.例子:边沿触发(ET) 一、水平触发(LT边沿触发(ET) 在电路中的有水平触发边沿触发的概念,在epoll读取事件下,水平触发可以理解为,蓝色那一部分,只要存在可读的情况,就会一直读取。而边沿触发,可以理解为红色箭头所指向,发生跳变的部分,就会触发一次。 在epoll中 events=EPOLLIN 为读取事件,LT模式 events=EPOLLIN|EPOLLET 为读取事件,ET模式 e

菊头蝙蝠的博客 5300

epollETLT模式详解

从man手册中,得到ETLT的具体描述如下EPOLL事件有两种模型:Edge Triggered (ET)Level Triggered (LT)假如有这样一个例子:1. 我们已经把一个用来从管道中读取数据的文件句柄(RFD)添加到epoll描述符2. 这个时候从管道的另一端被写入了2KB的数据3. 调用epoll_wait(2),并且它会返回RFD,说明它已经准备好读取操作4. 然后我们读取了

技术资料库 3万+

epoll ET模式LT模式分析

关于epoll的问题很早就像写文章讲讲自己的看法,但是由于ffrpc一直没有完工,所以也就拖下来了。Epoll主要在服务器编程中使用,本文主要探讨服务器程序中epoll的使用技巧。Epoll一般异步io结合使用,故本文讨论基于以下应用场合:   主要讨论服务器程序中epoll的使用,主要涉及tcp socket的相关api。  Tcp socket 为异步模式,包括socket的异步读写,

Roykuang的专栏 1518

EPOLLETLT模式

http://wenku.baidu.com/view/31253a29e2bd960590c677c8.html EPOLL事件分发系统可以运转在两种模式下:Edge Triggered (ET)、Level Triggered (LT)。 LT是缺省的工作方式,并且同时支持blockno-blocksocket;在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就

学习笔记 4132

epollLTET模式介绍

epollET模式如何设置,ET模式LT模式的区别

m0_62689947的博客 917

深度解析 EpollLT ET 模式

EpollLT ET 模式各有特点,在不同的应用场景下发挥着各自的优势。了解它们的工作原理、区别以及适用场景,有助于开发者根据实际需求选择合适的触发模式,从而编写高效、稳定的网络应用程序。在实际开发中,应根据具体业务场景性能要求,合理运用这两种模式,充分发挥 Epoll 的强大功能。希望本文对 EpollLT ET 模式的介绍,能为广大 Linux 网络开发者提供有益的参考。

AC的博客 795

epollLT模式(水平触发)ET模式(边沿触发)

epoll的触发模式是个引发讨论非常多的话题,网络上这方面总结的文章也很多,首先从名字上就不是很统一,LT模式常被称为水平触发、电平触发、条件触发,而ET模式常被称为边缘触发、边沿触发等,这些都是从英文翻译过来的,只不过翻译的时候有些差异,LT全称 level-triggered,ET全称 edge-triggered ...

AlbertS Home of Technology 1万+

关于EPOLLLTET模式以及阻塞非阻塞

EPOLLLT(水平触发)模式下,也就是默认的模式epoll_wait返回可读事件,表明socket一定收到了数据,我们可以调用read函数来读取数据。如果指定读取的数据大于缓冲区数据,无论socket是阻塞还是非阻塞的,read不会阻塞,read返回读取的真实数据。在read之后再次调用read,如果socket是阻塞的,read将阻塞,再次收到数据read才返回。此时如果指定读取的数据大于缓冲区,epoll_wait则不再触发,否则epoll_wait将再次触发,因为还有未读完的数据在缓冲区。 在E

luseysd的博客 5502

java epoll et lt_epollETLT模式详解

从man手册中,得到ETLT的具体描述如下EPOLL事件有两种模型:Edge Triggered (ET)Level Triggered (LT)假如有这样一个例子:1. 我们已经把一个用来从管道中读取数据的文件句柄(RFD)添加到epoll描述符2. 这个时候从管道的另一端被写入了2KB的数据3. 调用epoll_wait(2),并且它会返回RFD,说明它已经准备好读取操作4. 然后我们读取了...

weixin_42470969的博客 412

Epoll总结,ETLT模式Epoll(一)

Epoll总结 epoll 高效的原因: epoll使用三个方法来实现select方法要做的事情   1.新建epoll描述符==epoll_create()   2.epoll_ctrl(epoll描述符,添加或者删除所有待监控的连接)   3.返回的活跃连接 ==epoll_wait(epoll描述符)   与select相比,epoll分清了频繁调用不频繁调用的操作。例如,epoll_ctrl是不太频繁调用的,而epoll_wait是非常频繁调用的。这时,epoll_wait却几乎没有入参,这比se

qwert55kai的博客 962
上一篇: 服务器启动关系
下一篇: EPOLL的ET和LT模式
阿蓬江
博客等级 码龄15年 56粉丝 23原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值