epoll是Linux中用于IO多路复用的机制,在nginx和redis等软件中都有应用,redis的性能好的原因之一也就是使用了epoll进行IO多路复用,同时epoll也是各大公司面试的热点问题。

IO多路复用

IO多路复用是一种同步IO模型,使得一个线程就可以对多个文件描述符进行监听。当有文件描述符准备就绪时,函数就会返回,从而通知应用进行相应的处理;当没有描述符就绪时,函数就会阻塞。

IO多路复用对于网络应用来说是非常重要的,在没有IO多路复用时,应用一般通过同步阻塞(每个socket连接建立一个新线程,这将十分耗费系统性能)或者同步非阻塞(对所有socket进行反复遍历,当没有就绪描述符时就会做无用功)来实现,而这些方法的性能都不太好。

在Linux中,IO多路复用主要有三种方法select、poll和epoll。

select

int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

select是通过传递文件描述符数组fd_set*来实现的。当没有描述符准备就绪时,函数就会阻塞;当有一个或多个文件描述符准备就绪时就会返回,之后通过遍历数组找到准备就绪的描述符进行处理。select函数一般在所有操作系统中都会实现,因此具有良好的可移植性。

fd_set的大小是固定的,在Linux中一般为1024,本质是一个bitmap,通过FD_SET将描述符加入fd_set,通过对所有文件描述符依次调用FD_ISSET来判断是否准备就绪。

因此,select就有着以下的缺点:

  • select的文件描述符最大只能支持1024个
  • select需要通过遍历来判断是否准备就绪,因此时间复杂度为O(n)
  • 当监听文件描述符数量增加时,性能会明显下降
  • select内核态中通过轮询来判断文件描述符是否就绪
  • select每次调用都需要将fd_set从用户地址空间拷贝到内核地址空间中,函数返回时又要拷贝回来

poll

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd; // 文件描述符
short events; // 等待的事件
short revents; // 发生的事件
};

pollselect的主要改进就是没有了描述符数组的大小限制,没有最大连接数的限制。但是poll仍然需要进行遍历才能知道哪些文件描述符准备就绪,因此,select的缺点poll也有。

epoll

int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

epoll使用了三个系统调用来实现,epoll_create创建一个句柄,epoll_ctl向句柄中添加、删除或修改文件描述符,epoll_wait对句柄进行监听,当有文件描述符准备就绪后,就会通过events参数返回。返回的参数中仅包含准备就绪的文件描述符,也就是说不再需要通过遍历来进行判断。epoll通过回调机制来快速将文件描述符加入就绪链表,避免轮询;同时epoll内部使用红黑树来保存所有监听的文件描述符。

epoll有着以下的优点:

  • 没有最大文件描述符数量限制
  • 使用mmap,避免了每次wait都要将数组进行拷贝
  • 直接返回就绪的文件描述符,避免了遍历,时间复杂度为O(k),k为就绪文件描述符
  • 使用回调机制,当文件描述符就绪时会触发回调函数,将描述符加入到就绪链表,避免轮询
  • 监听的文件描述符数量对性能影响不大

但是epoll也不是一定比selectpoll好,当就绪的文件描述符很多时,即O(k)中的k接近n时,两者性能就比较接近了;当文件描述符数量较少时,两者性能也差不多;epoll的回调函数注册也会带来一定的性能开销。

触发方式

epoll有两种触发方式,水平触发(LT, level-triggered)和边缘触发(ET, edge-triggered)。通过一个例子来理解两种方式:

当描述符a中到达2kb数据,调用epoll_wait会返回a,之后从描述符中读取1kb数据,此时该描述符中仍有1kb数据,仍为就绪状态;第二次调用epoll_wait时,如果是LT,那么返回的描述符中仍包含a,如果为ET,那么就不包含a。

即ET只会在状态发生改变时触发,只返回一次,类似于上升沿触发;而LT只要处于就绪状态就会一直返回,类似于电平触发。

理论上ET的性能会比LT要好,但是ET要保证每次都要把数据全部处理完成,而LT使用起来就更加方便,不易出现bug。在实际当中两种的性能区别可以忽略,redis使用的就是LT方式。

IO多路复用与epoll机制浅析的更多相关文章

  1. python 网络编程 IO多路复用之epoll

    python网络编程——IO多路复用之epoll 1.内核EPOLL模型讲解     此部分参考http://blog.csdn.net/mango_song/article/details/4264 ...

  2. IO多路复用之epoll

    1.基本知识 epoll是在2.6内核中提出的,是之前的select和poll的增强版本.相对于select和poll来说,epoll更加灵活,没有描述符限制.epoll使用一个文件描述符管理多个描述 ...

  3. 网络编程socket 结合IO多路复用select; epool机制分别实现单线程并发TCP服务器

    select版-TCP服务器 1. select 原理 在多路复用的模型中,比较常用的有select模型和epoll模型.这两个都是系统接口,由操作系统提供.当然,Python的select模块进行了 ...

  4. IO多路复用之epoll总结

    1.基本知识 epoll是在2.6内核中提出的,是之前的select和poll的增强版本.相对于select和poll来说,epoll更加灵活,没有描述符限制.epoll使用一个文件描述符管理多个描述 ...

  5. linux网络编程 IO多路复用 select epoll

    本文以我的小型聊天室为例,对于服务器端的代码,做了三次改进,我将分别介绍阻塞式IO,select,epoll . 一:阻塞式IO 对于聊天室这种程序,我们最容易想到的是在服务器端accept之后,然后 ...

  6. python网络编程——IO多路复用之epoll

    1.内核EPOLL模型讲解     此部分参考http://blog.csdn.net/mango_song/article/details/42643971博文并整理 首先我们来定义流的概念,一个流 ...

  7. Linux IO多路复用之epoll网络编程及源码(转)

    原文: 前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网 ...

  8. IO多路复用之epoll(二)

    前一篇介绍了epoll的LT模式,LT模式注意epollout事件在数据全部写成功后需要取消关注, 或者更改为EPOLLIN. 而这次epoll的ET模式,要注意的是在读和写的过程中要在循环中写完或者 ...

  9. IO多路复用之epoll(一)讲解

    网络通信中socket有自己的内核发送缓冲区和内核接受缓冲区,好比是一个水池, 当用户发送数据的时候会从用户缓冲区拷贝到socket的内核发送缓冲区,然后从 socket发送缓冲区发出去, 当用户要读 ...

随机推荐

  1. [永恒之黑]CVE-2020-0796(漏洞复现)

    实验环境: 靶机:windows10 1903 专业版 攻击机:kali 2020.3 VMware:vmware14 实验工具: Python 3.8.5   msfconsole 实验PROC: ...

  2. Java学习日报8..4

    class ArrayUtil{ public static void reverse(int data[]) { int center=data.length/2; int head=0; int ...

  3. Pytest测试框架(一):pytest安装及用例执行

    PyTest是基于Python的开源测试框架,语法简单易用,有大量的插件,功能非常多.自动检测测试用例,支持参数化,跳过特定用例,失败重试等功能. 安装 pip install -U pytest  ...

  4. 批量修改vsphere共享存储多路径选择策略

    传统方式修改存储的多路径选择策略 首先说一下传统web界面操作方式: 可以看到至少需要6次才能修改完成一个.在生产环境中一般会挂载很多FC存储,这时候就需要一个批量快捷的方式来修改. 使用Powerc ...

  5. ViperX 300 Robot Arm 机械臂 “5自由度和360°全方位旋转”

  6. [C#] 使用 Excel 和 Math.Net 进行曲线拟合和数据预测

    以前在工作中遇到了一个数据错误的问题,顺便写下 用 Math.Net 解决的思路. 1. 错误的数据 上图是同一组探测器在同一天采集到的 19 次数据,总体来说重复性不错,但很明显最后 8 个探测器出 ...

  7. Vue概述

    Vue.js是一套构建用户界面的渐进式框架,采用自底向上增量开发的设计.Vue的核心库关注于视图(html),不仅易上手,还便于与第三方库或项目整合. 渐进式:一步一步,不是将所有的东西都学完才能使用 ...

  8. Sqoop(三)将关系型数据库中的数据导入到HDFS(包括hive,hbase中)

    一.说明: 将关系型数据库中的数据导入到 HDFS(包括 Hive, HBase) 中,如果导入的是 Hive,那么当 Hive 中没有对应表时,则自动创建. 二.操作 1.创建一张跟mysql中的i ...

  9. 4.5万字手把手教你实现MySQL TB级数据存储!!

    写在前面 业界对系统的高可用有着基本的要求,简单的说,这些要求可以总结为如下所示. 系统架构中不存在单点问题. 可以最大限度的保障服务的可用性. 一般情况下系统的高可用可以用几个9来评估.所谓的几个9 ...

  10. 【Java基础】Java 语言概述

    Java 语言概述 主要应用场景 JavaEE.大数据.Android 开发方向. 基础知识概述 编程语言核心结构 变量.基本语法.分支.循环.数组.- Java 面向对象的核心逻辑 OOP.封装.继 ...