【linux编程】 aio
aio
struct iocb结构体:
struct iocb {
__u64 aio_data; // 用户自定义数据(透传返回)
__u32 aio_key; // 保留(在某些系统上未使用)
__u32 aio_reserved1;
__u16 aio_lio_opcode; // 操作类型,比如读写(IO_CMD_PREAD、IO_CMD_PWRITE 等)
__s16 aio_reqprio; // 请求优先级(通常填 0)
__u32 aio_fildes; // 文件描述符
__u64 aio_buf; // 数据缓冲区的地址(必须是对齐分配)
__u64 aio_nbytes; // 要读/写的字节数
__s64 aio_offset; // 读写偏移
__u64 aio_reserved2; // 保留
__u64 aio_flags; // 标志位(一般设为 0)
__u64 aio_resfd; // 通知事件文件描述符(用于事件通知机制)
};
| 宏名 | 含义 |
| IO_CMD_PREAD | 异步读取 |
| IO_CMD_PWRITE | 异步写入 |
| IO_CMD_FSYNC | 刷新数据到磁盘 |
| IO_CMD_FDSYNC | 刷新 metadata |
| IO_CMD_NOOP | 空操作(用于测试) |
| 字段名 | 含义 |
|---|---|
aio_data |
用户自定义数据,会原样返回给你(通过 io_getevents 的结果 data 字段)。 |
aio_lio_opcode |
操作类型,例如: IO_CMD_PREAD(读)、IO_CMD_PWRITE(写) IO_CMD_FSYNC(刷盘)等。 |
aio_fildes |
要进行操作的文件描述符(必须是 open() 打开的 fd)。 |
aio_buf |
缓冲区地址,注意通常需要使用 aligned_alloc(如 512 字节对齐)。 |
aio_nbytes |
要操作的数据长度。 |
aio_offset |
文件偏移量。 |
aio_resfd |
用于 eventfd 通知机制(可选,一般设为 0)。 |
#include <libaio.h>
int io_submit(aio_context_t ctx_id, long nr, struct iocb **iocbpp);
参数说明
- ctx_id: 通过 io_setup 创建的 AIO 上下文 ID。
- nr: 要提交的 iocb 数量(即请求个数)。
- iocbpp: 一个指向 iocb 指针数组的指针,每个 iocb 描述一个 I/O 操作(读/写等)。
返回值
- 成功:返回成功提交的请求数量。
- 失败:返回负数,表示出错,对应 errno。
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <libaio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
int fd = open("test.txt", O_WRONLY | O_CREAT, 0644);
if (fd < 0) {
perror("open");
return 1;
}
// 初始化 AIO 上下文
aio_context_t ctx = 0;
if (io_setup(10, &ctx) < 0) {
perror("io_setup");
return 1;
}
// 准备写入数据
const char *data = "Hello, AIO!";
size_t len = strlen(data);
void *buf = aligned_alloc(512, len); // AIO 要求内存对齐
memcpy(buf, data, len);
// 创建 IOCB
struct iocb cb, *cbs[1];
memset(&cb, 0, sizeof(cb));
cb.aio_fildes = fd;
cb.aio_lio_opcode = IO_CMD_PWRITE;
cb.aio_buf = (uintptr_t)buf;
cb.aio_nbytes = len;
cb.aio_offset = 0;
cbs[0] = &cb;
// 提交 AIO 请求
if (io_submit(ctx, 1, cbs) < 0) {
perror("io_submit");
return 1;
}
// 等待完成
struct io_event events[1];
if (io_getevents(ctx, 1, 1, events, NULL) < 0) {
perror("io_getevents");
return 1;
}
printf("AIO write completed.\n");
io_destroy(ctx);
close(fd);
free(buf);
return 0;
}
函数原型:io_prep_pread 是 libaio 提供的一个辅助函数,用于简化设置 iocb 结构体,配置为执行异步 读操作(即 pread 模式)。
#include <libaio.h>
void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset);
参数说明:
| 参数 | 含义 |
|---|---|
iocb |
指向 struct iocb 的指针,将在函数中被填充为读操作。 |
fd |
要读取的文件描述符(通过 open() 打开)。 |
buf |
数据读取缓冲区(需内存对齐,常使用 aligned_alloc)。 |
count |
要读取的字节数。 |
offset |
从文件的哪个偏移开始读(类似于 pread 的位置参数)。 |
例子:
#include <libaio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int main() {
int fd = open("data.txt", O_RDONLY | O_DIRECT);
if (fd < 0) {
perror("open");
return 1;
}
aio_context_t ctx = 0;
io_setup(1, &ctx);
void *buf = aligned_alloc(512, 512); // O_DIRECT 要求对齐
memset(buf, 0, 512);
struct iocb cb, *cbs[1];
io_prep_pread(&cb, fd, buf, 512, 0); // 设置为 pread 操作
cbs[0] = &cb;
io_submit(ctx, 1, cbs);
struct io_event events[1];
io_getevents(ctx, 1, 1, events, NULL);
printf("Read data: %.20s\n", (char*)buf);
io_destroy(ctx);
close(fd);
free(buf);
return 0;
}
手动设置:
cb.aio_fildes = fd;
cb.aio_lio_opcode = IO_CMD_PREAD;
cb.aio_buf = (uintptr_t)buf;
cb.aio_nbytes = count;
cb.aio_offset = offset;

浙公网安备 33010602011771号