一次网络读操作分两个阶段:等数据就绪(网卡到内核缓冲区)、把数据从内核拷到用户空间。五种模型的区别在这两个阶段如何阻塞:1)阻塞 I/O——两阶段全程挂起;2)非阻塞 I/O——数据未就绪立即返回 EWOULDBLOCK,应用轮询重试,拷贝阶段仍阻塞;3)I/O 多路复用——select/epoll 阻塞等任一 fd 就绪,就绪后再调用阻塞 read 完成拷贝,用一次阻塞换管理大量连接;4)信号驱动 I/O——注册 SIGIO,就绪时收信号再 read;5)异步 I/O(AIO)——发起后立即返回,内核把「等数据 + 拷贝」全做完才回调通知,应用全程不阻塞。
关键辨析:前四种都是同步 I/O——因为它们在「数据拷贝」这一阶段都需要应用线程参与等待;只有 AIO 把拷贝也托管给内核,才是 POSIX 定义的真异步。对应到生态:Java 的 NIO 是多路复用(同步),NIO.2/AIO 在 Linux 底层其实是 epoll 模拟、Windows 上是真 IOCP;Node.js 的网络 I/O 走 epoll/kqueue(多路复用),文件 I/O 走 libuv 线程池模拟异步;Linux 的 io_uring 正在补真异步的课。追问方向:为什么高并发不选「非阻塞 + 忙轮询」(CPU 空转)、Reactor 与 Proactor 模式与同步/异步模型的对应关系。
(约 440 字)