io_uring 是 Linux 在 5.1 版本引入的一套新的异步 IO 实现。相比 Linux 在 2.6 版本引入的 AIO,io_uring 性能强很多,接近 SPDK[1],同时支持 buffer IO
io_uring 的作者 Jens Axboe 是 Linux 内核块层和其他块设备的维护者,同时也是 CFQ、Noop、Deadline 调度器、blktrace 以及 FIO 的作者,对内核块层非常熟悉
io_uring 只增加了三个 Linux 系统调用分别是 io_uring_setup
,io_uring_enter
和 io_uring_register
他们的入口都在 Linux 内核源码的 fs/io_uring.c
文件中
用户程序可以直接利用 syscall(__NR_xxx, ……)
的方式直接调用,使用起来很麻烦
由于直接使用系统调用较为复杂,Jens Axboe 还提供了封装好的用户态库 liburing,简化了 io_uring 的使用,代码位置在 github 上
liburing 仓库的 examples/
目录下提供了几个简单的样例程序:
文件
功能
其他
io_uring-test.c
读取一个文件的全部内容
-
io_uring-cp.c
复制一个文件的内容到另一个文件
利用 user_data
手动处理读写 IO 之间的依赖,读 IO 返回之后才下发写 IO
link-cp.c
复制一个文件的内容到另一个文件
同时下发读写,利用 IOSQE_IO_LINK
保证读写之间的依赖[2]
ucontext-cp.c
复制 n 个文件的内容到另 n 个文件
利用 ucontext
进行上下文切换,模拟协程
仔细阅读前三个用例,可以看出利用 io_uring 的一般流程如下:
利用 open
、fstat
等函数来打开文件以及元数据查看等操作
fd
(由 open
函数执行返回的)利用 io_uring_queue_init
初始化 struct io_uring ring
结构体
初始化 struct iovec *iovecs
结构体用于存放用户态 buffer 指针和长度
通过 io_uring_get_sqe
获取 sqe
通过 io_uring_prep_#OP
对 sqe
填充命令,buffer 以及 offset 信息
io_uring_sqe_set_data
对 sqe
附加 user_data
信息(该信息会在 cqe
中进行返回)通过 io_uring_submit
对整个 ring
的所有 sqe
进行下发
通过 io_uring_wait_cqe
或者 io_uring_peek_cqe
来获取 cqe
io_uring_wait_cqe
会阻塞当前线程直到有一个 cqe
返回io_uring_peek_cqe
不会阻塞,如果当前没有 cqe
,就会返回错误io_uring_cqe_get_data
可以从 cqe
中获取 user_data
通过 io_uring_cqe_seen
对当前 cqe
进行清除,避免被二次处理
所有 IO 完成后,通过 io_uring_queue_exit
将 ring
销毁
根据官方 Makefile
可以看出编译时有额外的三个条件
_GNU_SOURCE
宏,-D
宏定义-I
指定头文件目录位置liburing
库,-L
指定库位置,-l
指定库名即 gcc -D_GNU_SOURCE -I../src/include/ -L../src/ -luring -o test test.c
其中头文件目录下主要有三个头文件:
$ tree src/include/
src/include/
├── liburing
│ ├── barrier.h
│ └── io_uring.h
└── liburing.h
1 directory, 3 files
而 liburing
库也需要编译生成,推荐直接在 liburing
的顶层目录直接 make all
本文作者: ywang_wnlo
本文链接: https://ywang-wnlo.github.io/posts/c142853f.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
手机扫一扫
移动阅读更方便
你可能感兴趣的文章