Rust in Everything
基于 mio 1.2.4

核心类型

这一部分是本卷的重点,讲 mio 平台无关的那一层:用户直接打交道的几个类型。代码在 src/poll.rs、src/token.rs、src/interest.rs、src/event/、src/io_source.rs 和 src/waker.rs,加起来不到两千行,其中一大半是文档。这一层很薄:几乎每个方法都在一两步之内转到平台 Selector,所以每一章都会顺着读到 epoll 和 kqueue 的那几行,并在 Linux 和 macOS 上各跑一遍。

四章按「先看入口,再看流动的数据,再看两条主线的两端」排列:

  1. Poll 与 Registry:Poll → Registry → Selector → 一个 epoll / kqueue fd;poll 一行转成 epoll_wait / kevent,超时向上取整、超过约 24.8 天截到 c_int::MAX(1.2.1 修,#1948),EINTR 原样返回;try_clone 复制 fd 让别的线程注册;重复注册、未注册就注销这类误用在 debug、Linux、macOS 上的实测结果,以及 drop 不注销时 dup 出来的 fd 带来的问题。
  2. Token、Interest 与 Event:Token 原样进出内核(data.u64 / udata),mio 不维护映射表;Interest 是 NonZeroU8,平台专有的位按 cfg 隐藏;Event 透明包装平台结构,各个 is_* 方法在 epoll 和 kqueue 上查哪些标志位;Events 的容量就是一次 poll 的上限。
  3. Source 与 IoSource:event::Source 的三个方法;IoSource<T> 怎样把 std 类型接到 selector 上,debug 下的 SelectorId 检查;SourceFd 让任意 fd 参与;poll(2) 后备和 Windows 上 do_io 为什么要多做事。
  4. Waker:从别的线程叫醒阻塞中的 poll;一个 Poll 只能有一个 Waker(debug 下的 has_waker 断言);Linux 的 eventfd、macOS 的 EVFILT_USER、其他 Unix 的 pipe。
flowchart TB
  regnode["Registry::register"] --> srcnode["Source / IoSource"]
  srcnode --> selnode["Selector:epoll_ctl / kevent"]
  tok["Token + Interest"] --> regnode
  pollnode["Poll::poll"] --> selnode2["Selector:epoll_wait / kevent"]
  selnode2 --> evs["Events 里的 Event"]
  wakenode["Waker::wake"] -->|另一个线程| selnode2

💬 关联讨论

发起讨论
加载中...