You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用O_DIRECT时lio_listio()报EIO,求支持DIO的批量同步IO替代函数

解决O_DIRECT下lio_listio()返回EIO的问题及替代方案

首先需要明确:POSIX的lio_listio()本身是支持O_DIRECT的,你遇到的EIO错误大概率不是函数不支持DIO,而是违反了O_DIRECT的强制对齐要求。

先排查EIO的根本原因

使用O_DIRECT时,以下三个参数必须严格与文件系统的块大小(可通过stat的st_blksize字段获取)对齐:

  • 缓冲区地址:aiocb.aio_buf必须是块大小的整数倍,建议用posix_memalign()分配缓冲区,而非malloc()
  • 文件偏移:aiocb.aio_offset必须是块大小的整数倍
  • 读写长度:aiocb.aio_nbytes必须是块大小的整数倍

如果以上任意一项不满足,内核就会返回EIO错误,和lio_listio()本身无关。

若需替代方案(支持DIO且批量等待完成)

如果确认对齐没问题仍有异常,或者确实需要替代API,可以使用Linux原生AIO(区别于POSIX AIO)的io_submit() + io_getevents()组合,它天生支持O_DIRECT,且能批量提交IO请求并等待全部完成:

基本使用流程

  1. 初始化IO上下文:
    io_context_t ctx = 0;
    io_setup(MAX_IO_EVENTS, &ctx);
    
  2. 构造多个iocb结构(对应每个IO请求):
    struct iocb cb[NUM_REQUESTS];
    struct iocb *cbs[NUM_REQUESTS];
    for (int i = 0; i < NUM_REQUESTS; i++) {
        io_prep_pread(&cb[i], fd, buf[i], size[i], offset[i]);
        // 写请求替换为io_prep_pwrite
        cbs[i] = &cb[i];
    }
    
  3. 批量提交请求:
    long ret = io_submit(ctx, NUM_REQUESTS, cbs);
    
  4. 等待所有请求完成:
    struct io_event events[NUM_REQUESTS];
    long completed = io_getevents(ctx, NUM_REQUESTS, NUM_REQUESTS, events, NULL);
    
  5. 清理IO上下文:
    io_destroy(ctx);
    

注意:Linux原生AIO的API不属于POSIX标准,仅在Linux系统可用,其iocb结构与POSIX的aiocb不兼容。

内容的提问来源于stack exchange,提问作者mhsquare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:42:07