[转载] 理解 epoll 的事件触发机制
原文: 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 的事件触发机制的更多相关文章
- 【深入浅出Linux网络编程】 “基础 -- 事件触发机制”
回顾一下“"开篇 -- 知其然,知其所以然"”中的两段代码,第一段虽然只使用1个线程但却也只能处理一个socket,第二段虽然能处理成百上千个socket但却需要创建同等数量的线程 ...
- C#事件触发机制
C#的事件触发机制,类似于c++的回调函数机制 我先简单说一下,委托和事件的实质,后期再重开一篇博文来详细说 委托:指向方法的指针,类似于C的函数指针 事件:是一个可以存放0个或多个方法指针的数据结构 ...
- EventEmitter:nodeJs事件触发机制
Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列 Node.js 里面的许多对象都会分发事件:一个 net.Server 对象会在每次有新连接时触发一个事件, 一个 fs.r ...
- html元素双击事件触发机制猜想及疑惑
今天有个同事遇到一个奇怪的问题,我照着他的代码做了一些简化写了这个demo <!DOCTYPE html> <html> <head> <style type ...
- WinForm中的事件触发机制学习
在一个Form窗体中拖个按钮,双击后系统自动生成代码: private void button1_Click(object sender, EventArgs e) { } 同时在窗体的Initial ...
- Yii中事件触发机制
控制器初始化中添加事件处理方法,在需要触发的地方直接触发 public function init() { parent::init(); // TODO: Change the autogenera ...
- python 模拟事件触发机制
EventManager.py # -*- encoding: UTF-8 -*- # 系统模块 from queue import Queue, Empty from threading impor ...
- [转]as3事件流机制彻底理解
题记: 看过网上一些as3事件流的教程,觉得大多都讲得不甚清楚,让人不能直观的理解事件流.而这篇教程以将事件流过程比喻成捕鱼过程,形象简单. 在此基础上对于as3事件流总算有了全面的理解.事件流机制说 ...
- android的事件分发机制理解
android的事件分发机制理解 1.事件触发主要涉及到哪些层面的哪些函数(个人理解的顺序,可能在某一层会一次回调其它函数) activity中的dispatchTouchEvent .layout中 ...
随机推荐
- Linux中查找最耗性能的JAVA代码
在这里总结一下查找Linux.Java环境下最耗CPU性能的代码段的方法.基本上原理就是使用top命令查看最耗cpu的进程和线程(子进程).使用jstack把java线程堆栈给dump下来.然后,在堆 ...
- YTU 3002: 出栈顺序(栈和队列)
3002: 出栈顺序(栈和队列) 时间限制: 1 Sec 内存限制: 128 MB 提交: 80 解决: 20 题目描述 给出一个入栈序列,和一个出栈序列,判断该出栈序列是否正确. 输入 输入包含 ...
- Thinkphp3.2.3如何加载自定义函数库
方法一:将自定义函数库放在Common文件夹下的Common文件夹下,命名为function.php. 方法二:项目配置文件中定义LOAD_EXT_FILE参数.这个方法在3.1的开发手册中有. 参考 ...
- 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 ...
- [CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口
1 平台 转http://blog.csdn.net/misskissc/article/details/43063419 1.1 硬件 Table 1. 硬件(lscpu) Architecture ...
- Python3基础 count 返回指定元素在列表中的个数
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- tomcat和mysql安装配置总结
我安装的tomcat和mysql都是解压缩版的.安装和配置tomcat倒没花费我多少时间,主要是mysql,几乎花费了我一天的时间. Tomcat安装总结: 首先将下载好的tomcat压缩包解压放在其 ...
- oracle 触发器实现主键自增
drop table book; --创建表 create table book( bookId varchar2() primary key, name varchar2() ); --创建序列 c ...
- iOS 关于使用xib创建cell的两种初始化方式
[转]http://my.oschina.net/CgShare/blog/337406 方法一: 第一步: [self.collectionView registerNib:[UINib nibWi ...
- Cheatsheet: 2014 10.01 ~ 10.30
.NET ASP.NET Web Api: Unwrapping HTTP Error Results and Model State Dictionaries Client-Side HTTP 20 ...