本文为摘录,原文为: https://oxnz.github.io/2016/10/13/linux-aio/
1 Introduction
异步 I/O(AIO)是一种执行 I/O 操作的方法,使得发出 I/O 请求的进程在操作完成之前不被阻塞。相反,在提交 I/O 请求后, 该进程继续执行其代码,并可以随后检查所提交请求的状态。
在 Linux 中实现异步 I/O 有几种方式:
- 内核系统调用
- 用户空间库的实现并在内部使用系统调用(libaio)
- 在用户空间完全模拟 AIO 而不依赖任何内核支持(目前为止,使用 librt,属于 libc 的一部分)
2 I/O Models
Mode | Blocking | Non-blocking |
---|---|---|
Synchronous | read/write | read/write (O_NONBLOCK) |
Asynchronous | I/O (select/poll/epoll) | multiplexing AIO |
3 AIO System Calls
3.1 ABI Interface
AIO 系统调用入口点位于内核源代码中的 fs/aio.c
文件中。导出到用户空间的类型和常数位于 /usr/include/linux/aio_abi.h
头文件中。
Linux 内核仅提供了 5 个用于执行异步 I/O 的系统调用。
#include <linux/aio_abi.h>
int io_setup(unsigned nr_events, aio_context_t *ctxp);
int io_destroy(aio_context_t ctx);
int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp);
int io_cancel(aio_context_t ctx, struct iocb *, struct io_event *result);
int io_getevents(aio_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *timeout);
struct iocb
: 每个提交到 AIO 上下文的 I/O 请求都由一个 I/O 控制块结构表示 -struct iocb
io_submit()
接受 AIO 上下文 ID、数组的大小和数组本身作为参数。 需要注意的是,数组应包含指向 iocb 结构的指针,而不是结构本身。
io_submit()
的返回代码可以是以下值之一:
ret = (已提交的 iocbs 数量)
理想情况,所有 iocbs 都被接受并正在处理。
0 < ret < (已提交的 iocbs 数量)
io_submit()
系统调用会逐个处理传递数组中的 iocbs,从第一个条目开始。如果某个 iocb 的提交失败,系统会在这一 点停止并返回失败的 iocb 的索引。无法知道具体的失败原因。然而,如果第一个 iocb 的提交失败,请参考点 C。ret < 0
出现这种情况有两个原因:
- 在
io_submit()
开始迭代数组中的 iocbs 之前,出现了某些错误(例如,AIO 上下文无效)。 - 第一个 iocb (cbx[0]) 的提交失败。
- 在