mio 源码解析
全卷只对着一个版本写:
| crate | 版本 | tag | commit | 日期 |
|---|---|---|---|---|
| mio | 1.2.4 | v1.2.4 | 79d1417 | 2026-10-03 |
mio 是 tokio 下面那一层。tokio 卷的 IO 驱动讲的是 tokio 怎么用 mio:反应器每轮调一次 Poll::poll,按 token 找回 ScheduledIo、置就绪位、唤醒任务;从 TcpStream::read 到挂起讲任务读到 WouldBlock 之后怎么挂起。那几页把 mio 当成一个黑盒:「注册一下」「poll 一下」。这一卷打开这个黑盒,看这两个动作各变成哪几个系统调用,以及 Linux、macOS、Windows 和其他 Unix 上为什么不一样。
mio 只做一件事:把「这个 fd 什么时候可读、可写」从操作系统那里取回来。全卷沿两条线展开:
- 注册主线(一次
register):TcpListener::bind得到一个非阻塞 socket,包在IoSource<T>里;Registry::register(&mut source, Token, Interest)经event::Source::register落到平台的Selector。Linux 上是一次epoll_ctl(EPOLL_CTL_ADD),标志EPOLLIN|EPOLLRDHUP|EPOLLET,Token原样放进data;macOS 上是一次kevent,关心读就提交一个EVFILT_READ、关心写就提交一个EVFILT_WRITE,都带EV_CLEAR,Token放进udata。mio 自己不维护 fd 到 token 的表。 - 事件主线(一次
poll):Poll::poll(&mut events, timeout)落到epoll_wait或kevent,内核把就绪项直接写进Events里的Vec;用户遍历Event,token()、is_readable()这些方法只是在解释平台的标志位;然后对 source 做非阻塞 I/O,直到WouldBlock,再回去poll。Waker是这条线上的旁路:另一个线程wake(),让阻塞中的poll带着 waker 的 token 返回。
两条线每一步对应的源码和页面,见怎么读这一卷。
flowchart TB intro[00 导读] --> overview[01 全景] overview --> core[02 核心类型] core --> plat[03 平台实现] plat --> net[04 网络类型] net --> design[05 设计取舍] design --> pit[06 常见坑] pit --> site[07 在本站中] site --> hands[08 动手]
实验环境
系统调用级别的说法都用真实程序证明。macOS(kqueue)上直接 cargo run;Linux(epoll)上把程序交叉编译成 aarch64 musl 静态二进制,放进 Apple container 里的 Alpine(内核 6.12.28)运行,用 strace 记下每一个 epoll_ctl、epoll_pwait、eventfd2、accept4。每个实验都注明平台;同一个程序在两个平台上结果不同的地方,两边的输出都贴出来。
各部分
- 00 导读:锁定的版本,1.2.1(本站锁的版本)到 1.2.4 的每一处改动落在哪个平台;两条主线、阅读路线、实验环境;
src/的平台分层、三个 feature 和sys/shell、每个平台用哪个 selector、测试与 CI。 - 01 全景:就绪模型和完成模型,mio 为什么选「就绪 + 边沿触发」,不做什么;一个最小的事件循环在 macOS 和 Linux 上各跑一次。
- 02 核心类型:本卷重点。
Poll与Registry,Token、Interest与Event,Source与IoSource,Waker。 - 03 平台实现:epoll、kqueue、
poll(2)后备实现,以及 Windows 上怎么用 IOCP 和 AFD 模拟出就绪通知。 - 04 网络类型:
TcpListener/TcpStream的非阻塞细节,UDP、Unix 域套接字和 pipe。 - 05 设计取舍:把各章的取舍汇总到一起。
- 06 常见坑:用报错原文或现象做标题,每个都先跑出最小复现。
- 07 在本站中:本站不直接用 mio,全部经由 tokio;生产(Linux)和开发(macOS)上同一个程序的系统调用对照;本站锁的 1.2.1 与本卷的差异。
- 08 动手:不用 mio,直接用
libc写一个只支持 epoll 的迷你 mio。
从「导读」开始。只想会用 mio 的读者,读 01 全景、02 核心类型、04 网络类型和常见坑;想读懂实现的,按顺序读。02 是全卷的重点:两条主线都从那里的四个类型出发,03 再分平台往下走。
💬 关联讨论
发起讨论加载中...