Linux 异步API:io_uring介绍


io_uring:

高性能异步I/O框架

  • 能显著提高IO密集型应用的性能。

  • linux5.1内核正式引入,取缔传统的AIO。

  • 作者Jens Axboe也是CFQ、Noop、Deadline、Fio等的作者

  • 性能接近SPDK,并支持buffer IO


width:800px


应用

一些项目开始做尝试性应用:

  • RocksDb实现了MultiRead(),使用io_uring进行批量下发读io。
  • TiKV扩展了WAL、SSTable等写入使用io_uring。
  • SPDK在通用块层加入了io_uring支持
  • cephredis

linux io系统调用发展历程

(同步接口:)

➔ read(2)/write(2)

➔ pread(2)、readv(2)、preadv(2)、preadv2(2)

(异步接口:)

➔ aio_read(2)/aio_write(2)

➔ io_uring since Linux Kernel 5.1


1. 同步读写流程

device
kernel
user
Buffer IO
Direct IO
设备
Page Cache
VFS: vfs_read()
文件系统
块IO层
read()

1. 同步读写流程

  • 发出IO后,程序进入sleep状态,直到IO操作完成width:600px

  • 可想,随着存储设备越来越快,程序越来越复杂,该阻塞方式不够用了。


2. 异步IO:aio

  • aio实现了一套异步IO框架(since linux 2.5)。

width:600px

  • 相对同步阻塞IO,提高了性能。

2. 异步IO:aio

但是!

aio一直被认为难以使用效率低下

  • 只支持Direct IO。不支持Buffer IO,对大部分常规应用无用处。
  • 部分内部实现仍然会阻塞。
  • 未考虑扩展性,改动极其复杂。

3. io_uring

解决了aio的问题,统一了接口。

  • 真正异步,不会发生阻塞。
  • 支持所有IO模式。
  • 支持轮询模式(poller)等高级特性,针对不同场景,性能更好。
  • 灵活、可扩展。

io_uring基本原理

  • 每个io_uring有两个环形队列(ring),app和kernel共享,(类似NVMe):

    1. 提交队列:submission queue(SQ

    2. 完成队列:completion queue(CQw:600px


使用ring buffer(SQ、CQ)好处

  • 省去应用和内核间的内存拷贝。

  • 无锁操作,通过几个简单头尾指针移动就能完成交互。

  • 内核轮询模式下,无需系统调用。

    ​ 内核线程轮询处理SQ,应用只需监控CQ即可。image-20220506163532753


使用

三个系统调用
  • io_uring_setup(2):设置上下文,创建SQ、CQ等
  • io_uring_register(2):注册文件、缓存区
  • io_uring_enter(2):初始化和完成IO,支持很多操作

使用起来还是比较复杂,Jens Axboe提供了封装好的liburing库,简化了使用。


总结

  • io_uring的开发给Linux编程带来革命性变化,统一了Linux异步接口。
  • 使开发者能更高效地使用Intel Optane等高速介质。

谢谢

参考:

[译] Linux 异步 I/O 框架 io_uring:基本原理、程序示例与性能压测(2020

异步IO引擎——io_uring设计与实现

【io_uring】简介和使用_ywang_wnlo的博客

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐