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. Java基础集合简单总结

    集合 Collection单列集合有List 和 Set List集合有: ArrayList集合 特点: 1.存取有序 可以重复 有索引 2.底层是数组实现,查询快,增删慢 ArrayList底层: ...

  2. 10分钟带你入门git到github

    git的产生背景 开局先来一个故事吧,故事看完如果不想看枯燥无味的指令,没关系我已经把这篇文章的内容录制成了一个视频,点击文末阅读原文就可以观看.或者说你已经熟练掌握git的使用了,可以直接跳到总结部 ...

  3. 一台PC端安装多店仓信息的删除

    如图所示,安装了多店仓,想要删除其中莫一店仓信息! 步骤一:先找到对应目录,一般默认的目录为C:\Users\xxxx\AppData\Roaming\WebPos2.0\bosnatweiniman ...

  4. haproxy 支持 websocket

    haproxy支持websocket feat 通过嗅探http请求中的Connection: Upgrade Upgrade: websocket头部,来自动识别是否是websocket连接,识别成 ...

  5. Servlet[JAX-RS Servlet]的Servlet.init()引发异常

    代码环境 Eclipse2017 : 问题出现: 在测试Hello servlet时发生 org.apache.catalina.core.ApplicationContext log严重: Serv ...

  6. 观《if (domain logic) then CQRS, or Saga?》所悟

    引言 Udi Dahan曾在2017年阿姆斯特丹的DDD欧洲年会上发表过一篇演讲--if (domain logic) then CQRS, or Saga.视频是UP主从Youtube搬运的,我听力 ...

  7. Shiro配置Session检测时Quartz版本冲突

    项目背景: shiro 1.3 + quartz 2.x 2018-9-11 22:20:35补充: 经过测试,本人发现 ,通过实现 org.apache.shiro.session.mgt.Exec ...

  8. java进阶(31)--TreeSet集合、TreeMap集合、自平衡二叉树

    一.TreeSet集合简单 1.TreeSet集合底层是一个TreeMap 2.TreeMap集合底层是一个二叉树 3.放到TreeSet集合的元素等同于放到TreeMap集合的Key部分 4.Tre ...

  9. MySQL select 查询之分组和过滤

    SELECT 语法 SELECT [ALL | DISTINCT] {* | table.* | [table.field1[as alias1][,table.field2[as alias2]][ ...

  10. 我在华为OD的275天

    目录 0 - 时间线 1 - 为什么会去华为 OD 2 - 华为 OD 的工作内容 3 - OD 与华为自有员工的对比 4 - 那,到底要不要去华为 OD? 5 - 网传的 OD 转华为正编,真的假的 ...