核心类型
这一部分是本卷的重点,讲 mio 平台无关的那一层:用户直接打交道的几个类型。代码在 src/poll.rs、src/token.rs、src/interest.rs、src/event/、src/io_source.rs 和 src/waker.rs,加起来不到两千行,其中一大半是文档。这一层很薄:几乎每个方法都在一两步之内转到平台 Selector,所以每一章都会顺着读到 epoll 和 kqueue 的那几行,并在 Linux 和 macOS 上各跑一遍。
四章按「先看入口,再看流动的数据,再看两条主线的两端」排列:
- 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 带来的问题。 - Token、Interest 与 Event:
Token原样进出内核(data.u64/udata),mio 不维护映射表;Interest是NonZeroU8,平台专有的位按 cfg 隐藏;Event透明包装平台结构,各个is_*方法在 epoll 和 kqueue 上查哪些标志位;Events的容量就是一次poll的上限。 - Source 与 IoSource:
event::Source的三个方法;IoSource<T>怎样把 std 类型接到 selector 上,debug 下的SelectorId检查;SourceFd让任意 fd 参与;poll(2)后备和 Windows 上do_io为什么要多做事。 - 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
💬 关联讨论
发起讨论加载中...