原文: 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. count(*)、count(val)和count(1)的解释

    一.关于count的一些谣言: 1.count(*)比count(val)更慢!项目组必须用count(val),不准用count(*),谁用扣谁钱! 2.count(*)用不到索引,count(va ...

  2. csdn在线编程里面的一个排列组合题

    是csdn在线编程里面的一个问题 回文字符串是指从左到右和从右到左相同的字符串,现给定一个仅由小写字母组成的字符串,你可以把它的字母重新排列,以形成不同的回文字符串. 输入:非空仅由小写字母组成的字符 ...

  3. River Hopscotch(二分POJ3258)

    River Hopscotch Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9263 Accepted: 3994 Descr ...

  4. Removing Columns 分类: 贪心 CF 2015-08-08 16:10 10人阅读 评论(0) 收藏

    Removing Columns time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  5. Drainage Ditches 分类: POJ 图论 2015-07-29 15:01 7人阅读 评论(0) 收藏

    Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 62016 Accepted: 23808 De ...

  6. python访问mysql将返回的表转化为json

    ## Licensed to the Apache Software Foundation (ASF) under one or more# contributor license agreement ...

  7. android 入门 004 (同一个方法,点击实现不同的效果)

    同一个方法,点击实现不同的效果 <Button android:id="@+id/btn3" android:layout_width="wrap_content& ...

  8. 【Web】简谈如何监听浏览器的关闭

    > 参考的优秀文章 beforeunload实现关闭离开的提示 想起以前做的一个小系统,一个企业内部小型的测试系统,让考生在给定时间内完成考试,如果考生中退出,那么下次进来可以利用剩余的考试时间 ...

  9. 关于mysql varchar 类型的最大长度限制

    Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This ...

  10. BZOJ 2568 比特集合

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2568 题意:维护一个集合S,支持以下操作: (1)INS M : 将元素 M 插入 ...