【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;

 

posted @ 2018-05-09 16:08  苏格拉底的落泪  阅读(208)  评论(0)    收藏  举报