epoll 相关的系统调用有以下三个,这里简述下当调用对应函数后,内核的具体实现

epoll_creat( )

  1. 在内核注册文件系统 eventpollfs,挂载此文件系统
    (linux一切皆文件,便于处理)
     
    若返回指针,指针如果出错则无法判断,而 fd 可以通过 current -> files -> fd_array[] 找到其真伪
    epoll_creat 为什么返回一个 fd?因为它对应的就是这个文件系统中创建的新文件
     

  2. 创建两个内核 cache(频繁分配小块内存,应该创建 kmem_cahe 来做内存池),分别存放 struct epitem(事件信息) 和 eppoll_entry (用于挂在设备等待队列下)
    创建struct eventpoll(红黑树根/就绪链表)结构,放入 file -> private data
    (一个新创建的epoll文件带有一个struct eventpoll 结构,这个结构上再挂一个红黑树,而这个红黑树就是每次 epoll_ctl 时 fd 存放的地方)
     

epoll_ctl( )

  1. 检测红黑树中有没有当前 fd 有则返回,没有则插入树中:
    ep_insert( )
    创建 struct eppoll_entry(为了放入设备等待队列)
    设置其唤醒回调函数为 ep_poll_callback
    加入设备等待队列 (设备驱动)
    (当设备就绪,唤醒等待队列上的等待者时,ep_poll_callback就会被调用,将 epitem 放入 rdlist,每次调用 epoll_wait 就只收集 rdlist 里的 fd 就可以了)
     

ET/LT 工作模式的区别

来自百度百科的解释:

LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表。
 
ET (edge-triggered)是高速工作方式,只支持non-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认。
 
ET和LT的区别就在这里体现,LT事件不会丢弃,而是只要读buffer里面有数据可以让用户读,则不断的通知你。而ET则只在事件发生之时通知。可以简单理解为LT是水平触发,而ET则为边缘触发。LT模式只要有事件未处理就会触发,而ET则只在高低电平变换时(即状态从1到0或者0到1)触发。
 

对应的具体实现如下
在内核中除了上面提到的就绪队列 rdlist 外,还另外维护了一个队列 txlist,用于内核空间与用户空间的缓冲
在 LT 模式下,当我们调用 epoll_wait() 时:

  1. 睡眠 & 检查 rdlist 是否为空
    调用 ep_poll()
  2. 把 txlist 里的 fd 拷给用户空间,然后 ep_reinject_items 把一部分 fd 从 txlist 里返还给 rdlist 以便下次还能从 rdlist 中发现它
    调用 ep_reinject_items()
  3. 将 txlist 中 没有标注 EPOLLET 且事件被关注的 fd 重新放回 rdlist,下一次 epoll_wait() 时会再次响应

 
ET 模式的过程同上,区别在于仅把 rdlist 里的 fd 挪到 txlist(挪完后 rdlist 就空了),不会再放回去
事件发生后第一次通知后如果没有处理完所有的 fd,那么不会再次响应

Linux I/O复用 —— epoll 部分源码剖析的更多相关文章

  1. Linux MMC 驱动子系统简述(源码剖析)

    1. Linux MMC 驱动子系统 块设备是Linux系统中的基础外设之一,而 MMC/SD 存储设备是一种典型的块设备.Linux内核设计了 MMC子系统,用于管理 MMC/SD 设备. MMC ...

  2. Linux设备驱动模型简述(源码剖析)

    1. Linux设备驱动模型和sysfs文件系统 Linux内核在2.6版本中引入设备驱动模型,简化了驱动程序的编写.Linux设备驱动模型包含设备(device).总线(bus).类(class)和 ...

  3. epoll(2) 源码分析

    epoll(2) 源码分析 文本内核代码取自 5.0.18 版本,和上一篇文章中的版本不同是因为另一个电脑出了问题,但是总体差异不大. 引子留下的问题 关键数据结构 提供的系统调用 就绪事件相关逻辑 ...

  4. linux 软件管理--yum工具及源码包

    目录 linux 软件管理--yum工具及源码包 一.yum基本概述 二.yum源的配置 三.yum实践案例 四.yum全局配置文件 五.yum签名检查机制 五.制作本地yum仓库 六.构建企业级yu ...

  5. linux下使用gdb对php源码调试

    title: linux下使用gdb对php源码调试 date: 2018-02-11 17:59:08 tags: --- linux下使用gdb进行php调试 调试了一些php的漏洞,记录一下大概 ...

  6. (转)Linux设备驱动之HID驱动 源码分析

    //Linux设备驱动之HID驱动 源码分析 http://blog.chinaunix.net/uid-20543183-id-1930836.html HID是Human Interface De ...

  7. Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现

    声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...

  8. 自己实现多线程的socket,socketserver源码剖析

    1,IO多路复用 三种多路复用的机制:select.poll.epoll 用的多的两个:select和epoll 简单的说就是:1,select和poll所有平台都支持,epoll只有linux支持2 ...

  9. socket_server源码剖析、python作用域、IO多路复用

    本节内容: 课前准备知识: 函数嵌套函数的使用方法: 我们在使用函数嵌套函数的时候,是学习装饰器的时候,出现过,由一个函数返回值是一个函数体情况. 我们在使用函数嵌套函数的时候,最好也这么写. def ...

随机推荐

  1. Django之多对多表之through第三张表之InlineModelAdmin后台内嵌

    话不多说,来看表结构 这里有两个表,一个是阶段表,一个是老师表,一个老师可以带多个阶段,一个阶段也可以由多个老师带,所以是多对多关系 # 阶段表 class Stage(models.Model): ...

  2. fenby C语言 P16

    while先判断,不符合,不执行 dowhile后判断,不符合,执行一次 #include <stdio.h> int main(){ int i=1,sum=0; do{ sum=sum ...

  3. 持久层框架JPA与Mybatis该如何选型

    一.现状描述 目前java 持久层ORM框架应用最广泛的就是JPA和Mybatis.JPA只是一个ORM框架的规范, 对该规范的实现比较完整就是Spring Data JPA(底层基于Hibernat ...

  4. RSA学习1

    对PEM文件(以前是一个邮件编码)进行编码,得到RSA公钥.国密的RSA标准,一般是tlv(tag-version)格式的. 明文hash后的数据进行BER编码再进行加密.-签名 对于RSA的结构,全 ...

  5. ArcGIS Engine空间分析之拓扑分析的实现

    简单介绍: 拓扑学是一门研究几何图形位置关系的科学. GIS所关注的拓扑主要集中在拓扑关系——存在于地理实体间的拓扑关系. 拓扑关系在GIS中起着描述两个地理实体的相对空间位置的重要作用.它是GIS空 ...

  6. Netty 入门,这一篇文章就够了

    Netty是Java领域有名的开源网络库,特点是高性能和高扩展性,因此很多流行的框架都是基于它来构建的,比如我们熟知的Dubbo.Rocketmq.Hadoop等,针对高性能RPC,一般都是基于Net ...

  7. 转:如何让phpmyadmin输入密码再进入

    对于很多不熟悉PHP环境安装的朋友来说,用集成环境可以更快的上手,更方便的搭建PHP的运行环境,但是,WAMP的集成环境仅仅是将底层基础工作做好了,有些个别关键的配置操作并没有集成到环境安装中,所以给 ...

  8. [2018-01-08] Python强化周的第一天

    Python强化周的第一天 学生管理系统-制作(成绩类)模块 class Score: lesson_name = "python" # 课程名 score = 0 # 分数 # ...

  9. [Pandas]利用Pandas处理excel数据

    Python 处理excel的第三包有很多,比如XlsxWriter.xlrd&xlwt.OpenPyXL.Microsoft Excel API等,最后综合考虑选用了Pandas. Pand ...

  10. java核心编程书上的一个错误

    书上说这段代码说明了java对对象不是采用的按引用调用 这明显错了,java还是引用传递,只是把引用对象的变量复制了,互换了x,y所指的对象,对a,b没有影响