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. Dubbo与Kubernetes集成

    Dubbo应用迁移到docker的问题 Dubbo是阿里开源的一套服务治理与rpc框架,服务的提供者通过zookeeper把自己的服务发布上去,然后服务调用方通过zk获取服务的ip和端口,dubbo客 ...

  2. Java内存模型相关原则详解

    在<Java内存模型(JMM)详解>一文中我们已经讲到了Java内存模型的基本结构以及相关操作和规则.而Java内存模型又是围绕着在并发过程中如何处理原子性.可见性以及有序性这三个特征来构 ...

  3. 明解C语言 入门篇 第三章答案

    练习3-1 #include <stdio.h> int main() { int x; int y; puts("请输入两个整数."); printf("整 ...

  4. NOIP201605玩具谜题-解题报告

    NOIP201605玩具谜题-解题报告                                                                         2019-11- ...

  5. idea 2019 1 spring boot 启动报错 An incompatible version [1.2.12] of the APR based Apache Tomcat Native library is installed, while Tomcat requires version [1.2.14]

    1.构建一个简单springboot工程,日志打印报错内容如下: 15:38:28.673 [main] DEBUG org.springframework.boot.devtools.setting ...

  6. 学习笔记51_MongoDB使用

    MongoDB的包: 例如:设置Mongodb端口 在命令行: F:\MongoDB>mongod.exe --port:3306 做集群: 安装和使用: 1.在服务中添加MongoDB ( 指 ...

  7. CAT客户端如何从Apollo中读取配置?

    运行环境 以下就是这个示例的运行环境,如果版本号不一样,区别也应该不会很大,可以根据实际情况做相应调整. JDK 8 spring boot 2.0.7.RELEASE cat-client 3.0. ...

  8. Mybatis精讲(一)---环境配置及架构梳理

    目录 简介 ORM模型 Hibernate Ibatis 环境搭建 jar 配置 xml方式配置 代码方式配置 两种方式对比 Mybatis结构 源码解读xml环境加载 映射器解读 Ibatis # ...

  9. ssm整合的登录

    新建一个web工程,主要结构如下: 数据库创建如下: 控制层的代码FormController 类 package codeRose.controller; import org.springfram ...

  10. PHP判断是否为手机端的方法

    PHP判断是否为手机端的方法 private function ismobile() { // 如果有HTTP_X_WAP_PROFILE则一定是移动设备 if (isset($_SERVER['HT ...