io_uring
io_uring 是 Linux 内核(从 5.1 版本开始引入)提供的一套 全新的、高性能异步 I/O(Asynchronous I/O)接口 。
简单来说,它的出现是为了解决 Linux 过去在 I/O 操作上的一系列性能瓶颈,被认为是 Linux I/O 领域近十几年来最大的变革之一。
可以从 “为什么要造它” 、 “它是怎么工作的” 以及 “它的优势在哪里” 这三个维度来解释。
1. 为什么要造 io_uring?(过去的问题)
在 io_uring 出现之前,Linux 处理高性能网络和磁盘 I/O 主要靠以下几种方式,但它们都有缺点:
read/write(同步阻塞 I/O):- 问题: 线程会被卡住等待磁盘或网络,效率极低,不适合高并发。
epoll(I/O 多路复用):- 原理: 它是 “就绪模型” (Readiness Model)。它只告诉你“这个文件描述符(FD)可以读了”,但真正的读写操作(
read/write)还是必须由应用程序自己调用,这依然会产生系统调用(Syscall)开销,且数据需要在内核态和用户态之间拷贝。 - 局限: 对于磁盘文件 I/O,
epoll并不真正支持(文件总是“就绪”的),所以它主要用于网络。
- 原理: 它是 “就绪模型” (Readiness Model)。它只告诉你“这个文件描述符(FD)可以读了”,但真正的读写操作(
- Linux Native AIO (
io_submit):- 问题: 这是老一代的异步 I/O,非常难用。它仅支持
O_DIRECT模式(必须绕过系统缓存),对 buffered I/O 支持极差,且在某些元数据操作时仍会阻塞。
- 问题: 这是老一代的异步 I/O,非常难用。它仅支持
核心痛点: 随着 NVMe SSD 的速度越来越快(甚至快过了 CPU 处理中断的速度)以及 Meltdown/Spectre 漏洞补丁导致系统调用(Syscall)的开销变大, 频繁的系统调用 和 内存拷贝 成为了性能瓶颈。
2. io_uring 是怎么工作的?(核心原理)
io_uring 的核心设计思想是 减少系统调用 和 减少内存拷贝 。它通过在用户态和内核态之间 共享内存(Ring Buffer) 来实现这一点。
架构核心:两个环形队列
io_uring 在内存中开辟了两块区域,由内核和用户程序共享(通过 mmap 映射):
- 提交队列 (Submission Queue, SQ):
- 用户程序充当“生产者”,把要做的 I/O 请求(比如“读取文件 A 的前 4k 数据”)放入这个队列。
- 完成队列 (Completion Queue, CQ):
- 内核充当“生产者”,当 I/O 完成后,把结果(比如“读取成功,返回 4096 字节”)放入这个队列。
工作流程
- 用户 将一个或多个 I/O 请求写入 SQ。
- 用户 调用一次系统调用(
io_uring_enter)通知内核:“嘿,我有新任务了”(在某些模式下甚至不需要这个通知)。 - 内核 从 SQ 中取任务去执行(异步的)。
- 内核 做完后,把结果写入 CQ。
- 用户 从 CQ 中读取结果。
3. io_uring 的三大杀手锏
A. 真正的全异步(Proactor 模式)
与 epoll 的“就绪通知”不同,io_uring 是 “完成通知” (Completion Model)。
- epoll: 告诉你“数据来了,你自己读”。
- io_uring: 你告诉内核“帮我把数据读到这个 buffer 里”,内核做完后告诉你“读完了,直接用吧”。
B. 零拷贝与内存共享
由于提交队列和完成队列都在 共享内存 中,用户提交任务和内核返回结果时, 不需要进行系统调用之间的数据结构拷贝 。这大大节省了 CPU 周期。
C. 轮询模式 (Polling Mode) - 性能极致
io_uring 支持一种“内核轮询”模式(IORING_SETUP_SQPOLL)。
在这种模式下,内核会启动一个内核线程不停地检查 SQ 队列。
- 结果: 用户程序提交 I/O 任务时, 完全不需要任何系统调用 !你只要把任务写进内存,内核线程立刻就能看见并执行。这是目前 Linux 下 I/O 的性能天花板。
4. io_uring 与 epoll 的对比
5. 谁在使用 io_uring?
由于它是较新的技术(2019年发布),普及需要时间,但高性能软件已经纷纷跟进:
- 存储/数据库: RocksDB, PostgreSQL, MySQL (在开发中), ScyllaDB。
- Web 服务器/代理: Envoy, Nginx (正在实验性支持)。
- 运行时/语言库:
- Node.js (libuv): 已经开始集成。
- Rust (Tokio / Glommio): 对 io_uring 支持非常积极,尤其是 Glommio 框架是专门为 io_uring 设计的。
- Go: 也在进行相关的集成实验。
总结
io_uring 是 Linux I/O 的未来。
它不仅仅是一个新的 API,更是一套通过 共享内存 和 环形队列 来彻底消除内核与用户态交互开销的机制。对于需要极致 I/O 性能(如高频交易、超高速 SSD存储、千万级并发网关)的应用来说,io_uring 是目前的终极解决方案。

