原文: http://weibo.com/p/1001603862394207076573?sudaref=weibo.com

epoll的I/O事件触发方式有两种模式:ET(Edge Triggered)和LT(Level Triggered)。

这个触发模式其实是events(事件)的属性,该属性是和POLLIN、POLLOUT等属性并列且混杂使用的,而events有时依附在fd(文件描述符)上的,所以可以说:这个触发模式是events所依附的fd的属性。区分events和fd的原因是kernel内部实现也是这么区分的:events由eppoll_entry代表,fd由epitem代表。

先简单了解下这两种模式。

LT模式就是针对一个上报事件,如果没处理完,那么下次该事件还在,可以继续处理。而相同场景下的ET模式处理是:下次该事件就不在了,也就是说只通知一次,不给第二次处理的机会。epoll的默认模式是LT,毕竟select/poll都仅仅支持LT模式。

先看ET模式。

ET模式的基本说明:

An application that employs the EPOLLET flag should use nonblocking file descriptors to avoid having a blocking read or write starve a task that is handling multiple file descriptors.  The suggested way to use epoll as an edge-triggered (EPOLLET)  interface  is  as follows:

1)with nonblocking file descriptors; and

2)by waiting for an event only after read(2) or write(2) return EAGAIN.

By  contrast,  when  used  as  a  level-triggered  interface  (the default, when EPOLLET is not specified), epoll is simply a faster poll(2), and can be used wherever the latter is used since it shares the same semantics.

可见,ET模式时要使用非堵塞的fd,并且要采用穷极方式来处理事件(直到得到满意的EAGAIN返回值)。我们再仔细看看处理事件的流程:

Q:Do I need to continuously read/write a file descriptor until EAGAIN when using the EPOLLET flag (edge-triggered behavior) ?

A:Receiving an event from epoll_wait(2) should suggest to you that such file descriptor is ready for the requested I/O  operation. You must consider it ready until the next (nonblocking) read/write yields EAGAIN.  When and how you will use the file descriptor is entirely up to you.

For packet/token-oriented files (e.g., datagram socket, terminal in canonical mode), the only way to detect the end of the read/write I/O space is to continue to read/write until EAGAIN.

For stream-oriented  files (e.g., pipe, FIFO, stream socket), the condition that the read/write I/O space is exhausted can also be detected by checking the amount of data read from / written to the target file descriptor.  For example, if you call  read(2) by  asking to read a certain amount of data and read(2) returns a lower number of bytes, you can be sure of having exhausted the read I/O space for the file descriptor.  The same is true when writing using write(2).  (Avoid this latter technique if you can‐not guarantee that the monitored file descriptor always refers to a stream-oriented file.)

也就是说,判断结束的方法有两种:看EAGAIN返回值;比较期望count和真实count。

对于ET模式,需要注意的一点是:在eventpoll(标识一个epoll实例)的就绪队列里,放的是events所依附的fd,而不是events本身。这会导致一种捎带现象:一个POLLIN事件触发一次后,不再出现了,虽然用户没有处理完。但是一个新的POLLOUT事件来了,此时旧的POLLIN事件又捎带出来了。(打个比方,人是fd,新帐旧帐是不同的events,则类似于:有旧账没关系,不碰面就行。就怕有新帐,有了新帐,就得碰面并且新帐旧账一起算。。。)

我们觉得,ET模式还是很合理的,跟网卡的NAPI读包方式很像,都带有poll(高效:对于epoll而言,毕竟节省了很多额外的epoll系统调用的次数)特色。。。

再看LT模式。

为何是先看ET再看LT?因为从代码实现上看,我们觉得epoll应该是在支持ET之后才增加的支持LT。

对LT的支持很简单,仅需要在已有ET实现的基础上多几行代码:

在处理上报事件之后又重新将事件放回到eventpoll(标识一个epoll实例)的就绪队列里,也就是说直接给了这些事件(实际上是epitem,即事件所依附的文件描述符)第二次处理的机会(ET模式是没有这个机会的),虽然这个机会可能不需要:因为用户可能第一次就穷极处理完了该事件。可见,LT模式的处理有点低效(特别是在fd数量很大的情况下)。

综上,epoll实现了一种I/O事件的通知方式的两种模式:LT和ET,从效率上看,ET应该更有优势。

[转载] 理解 epoll 的事件触发机制的更多相关文章

  1. 【深入浅出Linux网络编程】 “基础 -- 事件触发机制”

    回顾一下“"开篇 -- 知其然,知其所以然"”中的两段代码,第一段虽然只使用1个线程但却也只能处理一个socket,第二段虽然能处理成百上千个socket但却需要创建同等数量的线程 ...

  2. C#事件触发机制

    C#的事件触发机制,类似于c++的回调函数机制 我先简单说一下,委托和事件的实质,后期再重开一篇博文来详细说 委托:指向方法的指针,类似于C的函数指针 事件:是一个可以存放0个或多个方法指针的数据结构 ...

  3. EventEmitter:nodeJs事件触发机制

    Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列 Node.js 里面的许多对象都会分发事件:一个 net.Server 对象会在每次有新连接时触发一个事件, 一个 fs.r ...

  4. html元素双击事件触发机制猜想及疑惑

    今天有个同事遇到一个奇怪的问题,我照着他的代码做了一些简化写了这个demo <!DOCTYPE html> <html> <head> <style type ...

  5. WinForm中的事件触发机制学习

    在一个Form窗体中拖个按钮,双击后系统自动生成代码: private void button1_Click(object sender, EventArgs e) { } 同时在窗体的Initial ...

  6. Yii中事件触发机制

    控制器初始化中添加事件处理方法,在需要触发的地方直接触发 public function init() { parent::init(); // TODO: Change the autogenera ...

  7. python 模拟事件触发机制

    EventManager.py # -*- encoding: UTF-8 -*- # 系统模块 from queue import Queue, Empty from threading impor ...

  8. [转]as3事件流机制彻底理解

    题记: 看过网上一些as3事件流的教程,觉得大多都讲得不甚清楚,让人不能直观的理解事件流.而这篇教程以将事件流过程比喻成捕鱼过程,形象简单. 在此基础上对于as3事件流总算有了全面的理解.事件流机制说 ...

  9. android的事件分发机制理解

    android的事件分发机制理解 1.事件触发主要涉及到哪些层面的哪些函数(个人理解的顺序,可能在某一层会一次回调其它函数) activity中的dispatchTouchEvent .layout中 ...

随机推荐

  1. Linux中查找最耗性能的JAVA代码

    在这里总结一下查找Linux.Java环境下最耗CPU性能的代码段的方法.基本上原理就是使用top命令查看最耗cpu的进程和线程(子进程).使用jstack把java线程堆栈给dump下来.然后,在堆 ...

  2. YTU 3002: 出栈顺序(栈和队列)

    3002: 出栈顺序(栈和队列) 时间限制: 1 Sec  内存限制: 128 MB 提交: 80  解决: 20 题目描述 给出一个入栈序列,和一个出栈序列,判断该出栈序列是否正确. 输入 输入包含 ...

  3. Thinkphp3.2.3如何加载自定义函数库

    方法一:将自定义函数库放在Common文件夹下的Common文件夹下,命名为function.php. 方法二:项目配置文件中定义LOAD_EXT_FILE参数.这个方法在3.1的开发手册中有. 参考 ...

  4. 2016年10月20日 星期四 --出埃及记 Exodus 19:4

    2016年10月20日 星期四 --出埃及记 Exodus 19:4 `You yourselves have seen what I did to Egypt, and how I carried ...

  5. [CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口

    1 平台 转http://blog.csdn.net/misskissc/article/details/43063419 1.1 硬件 Table 1. 硬件(lscpu) Architecture ...

  6. Python3基础 count 返回指定元素在列表中的个数

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  7. tomcat和mysql安装配置总结

    我安装的tomcat和mysql都是解压缩版的.安装和配置tomcat倒没花费我多少时间,主要是mysql,几乎花费了我一天的时间. Tomcat安装总结: 首先将下载好的tomcat压缩包解压放在其 ...

  8. oracle 触发器实现主键自增

    drop table book; --创建表 create table book( bookId varchar2() primary key, name varchar2() ); --创建序列 c ...

  9. iOS 关于使用xib创建cell的两种初始化方式

    [转]http://my.oschina.net/CgShare/blog/337406 方法一: 第一步: [self.collectionView registerNib:[UINib nibWi ...

  10. Cheatsheet: 2014 10.01 ~ 10.30

    .NET ASP.NET Web Api: Unwrapping HTTP Error Results and Model State Dictionaries Client-Side HTTP 20 ...