注:之前写过两篇关于epoll实现的文章,但是感觉懂得了实现原理并不一定会使用,所以又决定写这一系列文章,希望能够对epoll有比较清楚的认识。是请大家转载务必注明出处,算是对我劳动成果的一点点尊重吧。另外,文中如果有不全面或者不正确的地方还请大家指出。也可以私信或者发邮件:lvyilong316@163.com

1. ET模式实现分析

1.1 ET和LT的实现区别

首先给出下面一张图,这张图是从我之前的一篇博文——epoll实现分析中摘取并细化的。这张图对理解ET模式已经epoll的工作过程只管重要,当然我自己总结出来后也感觉有的小成就,在这里与大家分享。

注:上图的poll不要理解成和select相似那个poll,这是通过epoll_ctl调用的。

下面简要分析一下epoll的工作过程:

(1) epoll_wait调用ep_poll,当rdlist为空(无就绪fd)时挂起当前进程,知道rdlist不空时进程才被唤醒。

(2) 文件fd状态改变(buffer由不可读变为可读或由不可写变为可写),导致相应fd上的回调函数ep_poll_callback()被调用。

(3) ep_poll_callback将相应fd对应epitem加入rdlist,导致rdlist不空,进程被唤醒,epoll_wait得以继续执行。

(4) ep_events_transfer函数将rdlist中的epitem拷贝到txlist中,并将rdlist清空。

(5) ep_send_events函数(很关键),它扫描txlist中的每个epitem,调用其关联fd对用的poll方法(图中蓝线)。此时对poll的调用仅仅是取得fd上较新的events(防止之前events被更新),之后将取得的events和相应的fd发送到用户空间(封装在struct epoll_event,从epoll_wait返回)。之后如果这个epitem对应的fd是LT模式监听且取得的events是用户所关心的,则将其重新加入回rdlist(图中蓝线),否则(ET模式)不在加入rdlist。

具体代码:

/* 扫描整个txlist链表... */

for (eventcnt = 0, uevent = esed->events;

!list_empty(head) && eventcnt < esed->maxevents;) {

/* 取出第一个成员 */

epi = list_first_entry(head, struct epitem, rdllink);

/* 然后从链表里面移除 */

list_del_init(&epi->rdllink);

/* 读取events,

* 注意events我们ep_poll_callback()里面已经取过一次了, 为啥还要再取?

* 1. 我们当然希望能拿到此刻的最新数据, events是会变的~

* 2. 不是所有的poll实现, 都通过等待队列传递了events, 有可能某些驱动压根没传

* 必须主动去读取. */

revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL) &

epi->event.events;

if (revents) {

/* 将当前的事件和用户传入的数据都copy给用户空间,

* 就是epoll_wait()后应用程序能读到的那一堆数据. */

if (__put_user(revents, &uevent->events) ||

__put_user(epi->event.data, &uevent->data)) {

/* 如果copy过程中发生错误, 会中断链表的扫描,

* 并把当前发生错误的epitem重新插入到ready list.

* 剩下的没处理的epitem也不会丢弃, 在ep_scan_ready_list()

* 中它们也会被重新插入到ready list */

list_add(&epi->rdllink, head);

return eventcnt ? eventcnt : -EFAULT;

}

eventcnt++;

uevent++;

if (epi->event.events & EPOLLONESHOT)

epi->event.events &= EP_PRIVATE_BITS;

else if (!(epi->event.events & EPOLLET)) {

/*

* If this file has been added with Level

* Trigger mode, we need to insert back inside

* the ready list, so that the next call to

* epoll_wait() will check again the events

* availability. At this point, noone can insert

* into ep->rdllist besides us. The epoll_ctl()

* callers are locked out by

* ep_scan_ready_list() holding "mtx" and the

* poll callback will queue them in ep->ovflist.

*/

/* 嘿嘿, EPOLLET和非ET的区别就在这一步之差呀~

* 如果是ET, epitem是不会再进入到readly list,

* 除非fd再次发生了状态改变, ep_poll_callback被调用.

* 如果是非ET, 不管你还有没有有效的事件或者数据,

* 都会被重新插入到ready list, 再下一次epoll_wait

* 时, 会立即返回, 并通知给用户空间. 当然如果这个

* 被监听的fds确实没事件也没数据了, epoll_wait会返回一个0,

* 空转一次.

*/

list_add_tail(&epi->rdllink, &ep->rdllist);

}

}

}

说明:

l epoll_wait返回的条件是rdlist不空,而使rdlist不空的途径有两个,分别对应图中的红线和蓝线。

l ET和LT模式下的epitem都可以通过红线方式加入rdlist从而唤醒epoll_wait,但LT模式下的epitem还可以通过蓝线方式重新加入rdlist唤醒epoll_wait。所以ET模式下,fd就绪(通过红线加入rdlist)只会被通知一次,而LT模式下只要满足相应读写条件就返回就绪(通过蓝线加入rdlist)。

l ET事件发生仅通知一次的原因是只被添加到rdlist中一次,而LT可以有多次添加的机会。

1.2 两种加入rdlist途径的不同

下面我们来分析一下图中两种将epitem加入rdlist方式(也就是红线和蓝线)的区别。

l 红线:fd状态改变是才会触发。那么什么情况会导致fd状态的改变呢?

对于读取操作:

(1) 当buffer由不可读状态变为可读的时候,即由空变为不空的时候。

(2) 当有新数据到达时,即buffer中的待读内容变多的时候。

对于写操作:

(1) 当buffer由不可写变为可写的时候,即由满状态变为不满状态的时候。

(2) 当有旧数据被发送走时,即buffer中待写的内容变少得时候。

l 蓝线:fd的events中有相应的时间(位置1)即会触发。那么什么情况下会改变events的相应位呢?

对于读操作:

(1) buffer中有数据可读的时候,即buffer不空的时候fd的events的可读为就置1。

对于写操作:

(1) buffer中有空间可写的时候,即buffer不满的时候fd的events的可写位就置1。

说明:红线是时间驱动被动触发,蓝线是函数查询主动触发。

彻底学会使用epoll(一)——ET模式实现分析相关推荐

  1. (转)彻底学会使用epoll(一)——ET模式实现分析

    注:之前写过两篇关于epoll实现的文章,但是感觉懂得了实现原理并不一定会使用,所以又决定写这一系列文章,希望能够对epoll有比较清楚的认识.是请大家转载务必注明出处,算是对我劳动成果的一点点尊重吧 ...

  2. EPOLL的工作模式 ET and LT

    近日又继续学习了一下EPOLL的工作模式,这会基本上搞清楚了,因而撰写了此篇文档进行描述.先来一段网上的介绍文档: EPOLL事件分发系统可以运转在两种模式下:Edge Triggered (ET). ...

  3. 基于Epoll的Reactor模式

    Reactor模式 Reactor模式的定义 Reactor模式中的主要角色 Epoll (ET)服务器 EventItem类的设计 Reactor类的设计 回调函数 套接字相关 引入线程池 Reac ...

  4. 手机如何测光照度_如何3分钟学会用手机的专业模式拍照?

    原标题:如何3分钟学会用手机的专业模式拍照? 说到专业模式,有些人可能在自己的手机上看到过,有些人可能从来没见过,一般稍微好点的安卓手机都有专业模式,苹果手机没有专业模式,不过可以下载Procam6辅 ...

  5. epoll 主从反应堆模式代码实现

    epoll 主从反应堆模式 学习极客时间<网络编程>. 将 epoll 主从反应堆模式 部分的代码单独剥离出来,并写了简单的makefile.方便大家学习. 代码地址:epoll_serv ...

  6. EPOLL在ET模式下会被触发多次么?

    前几天和同学一起讨论EPOLLONESHOT的作用,它的功能是这样的: 对于注册了EPOLLONESHOT事件的文件描述符,操作系统最多触发其上注册的包括可读,可写,错误中的一个,且只触发一次 刚一看 ...

  7. Epoll两种模式浅析(ET or LT)

    linux异步IO浅析  http://hi.baidu.com/_kouu/blog/item/e225f67b337841f42f73b341.html epoll有两种模式,Edge Trigg ...

  8. 五种高级IO | select poll epoll 水平触发模式 边缘触发模式 惊群问题

    一.高级IO 在介绍多路复用IO之前,先介绍一下其它四种高级IO: 阻塞IO: 在内核将数据准备好之前,系统调用会一直等待.所以的套集字默认是阻塞方式. 非阻塞IO: 在内核还未将数据准备好,则系统调 ...

  9. linux下select,poll,epoll的使用与重点分析

    好久没用I/O复用了,感觉差点儿相同都快忘完了.记得当初刚学I/O复用的时候花了好多时间.可是因为那会不太爱写博客,导致花非常多时间搞明确的东西,依旧非常easy忘记.俗话说眼过千遍不如手过一遍,的确 ...

最新文章

  1. 小腹下面是什么部位_为什么肚子上的肉最难减?说好的马甲线呢?
  2. ES5-5 参数默认值、递归、预编译、暗示全局变量
  3. 程序员修神之路--那些分布式事务解决方案
  4. dep指定版本 go_Go 1.12 版本的新特性
  5. 中国工程院院士和科学院院士有什么区别,谁贡献很大却没有入院士?
  6. 用js如何获取file是否存在
  7. 宏定义 object-c 单例
  8. project项目导入java路径_Eclipse项目怎么导入IDEA并运行(超详细)
  9. html项目_趣图:我是一个 HTML 开发者,你们看看我做的这个项目咋样?
  10. 服务器系统日期,系统日期和服务器日期不一致
  11. 索纳塔9 2.4L旗舰版 一手原车 诚意出售
  12. Win10华硕atk驱动怎么安装_正版win10下载好后怎么安装?正版win10安装教程
  13. 二维码生成器 python excel_python 自动生成excel
  14. 平安普惠系统上线申请表模板
  15. 获取火山无水印视频方法
  16. 求陈敏老师所著的《OPNET物联网仿真》中的模型IOT_Simulation.rar,万分感谢!
  17. JS 实现点击按钮实现超链接功能
  18. Java动态读取map里面的key值
  19. 文件上传控件SWFUpload使用指南分享
  20. 《0Day安全》之堆溢出

热门文章

  1. python ATM购物程序
  2. ubuntu系统下如何修改host
  3. android_Text
  4. C语言简单程序情话,给你一份程序员的“科技情话”,赶在双十一前脱单吧
  5. xml mysql 模糊查询_mybatis+Spring mysql的模糊查询问题
  6. python亲密度_859. 亲密字符串(Python)
  7. 文档词频矩阵_论文理解:从词嵌入到文档距离
  8. 《Linux杂记:一》
  9. 《MySQL——count()逻辑》
  10. 树、二叉树、二叉搜索树_检查二叉树是否为BST(二叉搜索树)