菜单

Administrator
发布于 2026-05-17 / 1 阅读
0
0

IO多路复用

一、简述

IO 多路复用是一种同步 IO 模型,实现一个线程可以监视多个文件句柄。一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出 cpu。

IO 是指网络 IO,多路指多个TCP连接(即 socket 或者 channel),复用指复用一个或几个线程。意思说一个或一组线程处理多个 TCP 连接。最大优势是减少系统开销小,不必创建过多的进程/线程,也不必维护这些进程/线程。

IO 多路复用的三种实现方式:select、poll、epoll


二、select 机制

基本原理

客户端操作服务器时就会产生这三种文件描述符(简称fd):writefds(写)、readfds(读)、和 exceptfds(异常)。select 会阻塞住监视 3 类文件描述符,等有数据、可读、可写、出异常或超时就会返回;返回后通过遍历 fdset 整个数组来找到就绪的描述符 fd,然后进行对应的 IO 操作。

优点

  • 几乎在所有的平台上支持,跨平台支持性好

缺点

  • 由于是采用轮询方式全盘扫描,会随着文件描述符 FD 数量增多而性能下降
  • 每次调用 select(),都需要把 fd 集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间)
  • 单个进程打开的 FD 是有限制(通过 FD_SETSIZE 设置)的,默认是 1024 个,可修改宏定义,但是效率仍然慢

三、poll 机制

基本原理

与 select 一致,也是轮询+遍历。唯一的区别就是 poll 没有最大文件描述符限制(使用链表的方式存储 fd)。

poll 缺点

  • 由于是采用轮询方式全盘扫描,会随着文件描述符 FD 数量增多而性能下降
  • 每次调用 select(),都需要把 fd 集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间)

四、epoll 机制

基本原理

没有 fd 个数限制,用户态拷贝到内核态只需要一次,使用时间通知机制来触发。通过 epoll_ctl 注册 fd,一旦 fd 就绪就会通过 callback 回调机制来激活对应 fd,进行相关的 io 操作。

epoll 之所以高性能是得益于它的三个函数:

  • epoll_create():系统启动时,在 Linux 内核里面申请一个B+树结构文件系统,返回 epoll 对象,也是一个 fd
  • epoll_ctl():每新建一个连接,都通过该函数操作 epoll 对象,在这个对象里面修改添加删除对应的链接 fd,绑定一个 callback 函数
  • epoll_wait():轮训所有的 callback 集合,并完成对应的 IO 操作

优点

  • 没 fd 这个限制,所支持的 FD 上限是操作系统的最大文件句柄数,1G 内存大概支持 10 万个句柄
  • 效率提高,使用回调通知而不是轮询的方式,不会随着 FD 数目的增加效率下降
  • 内核和用户空间 mmap 同一块内存实现(mmap 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间)

epoll 缺点

  • epoll 只能工作在 linux 下

epoll 应用

  • redisnginx

五、epoll 水平触发(LT)与边缘触发(ET)的区别

epoll 有 epoll LTepoll ET 两种触发模式,LT 是默认的模式,ET 是"高速"模式。

  • LT 模式下,只要这个 fd 还有数据可读,每次 epoll_wait 都会返回它的事件,提醒用户程序去操作
  • ET 模式下,它只会提示一次,直到下次再有数据流入之前都不会再提示了,无论 fd 中是否还有数据可读。所以在 ET 模式下,read 一个 fd 的时候一定要把它的 buffer 读完,或者遇到 EAGAIN 错误

评论