​​io_uring 实现异步写入 16MB-64MB 数据到文件(附:完整代码)​

​使用 io_uring 实现异步写入 16MB-64MB 数据到文件(完整代码)​

io_uring 是 Linux 高性能异步 I/O 框架,适用于大文件写入场景。以下是一个完整示例,将 ​​16MB~64MB 的随机数据​​异步写入文件,并确保高效性和正确性。


​1. 代码实现​

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <liburing.h>
#include <sys/stat.h>

#define BUF_SIZE (16 * 1024 * 1024)  // 16MB 缓冲区(可调整至64MB)
#define FILE_NAME "large_file.bin"

// 初始化io_uring
int setup_uring(struct io_uring *ring, unsigned entries) {
    int ret = io_uring_queue_init(entries, ring, 0);
    if (ret < 0) {
        perror("io_uring_queue_init");
        exit(EXIT_FAILURE);
    }
    return ret;
}

// 生成随机数据
void generate_data(char *buf, size_t size) {
    for (size_t i = 0; i < size; i++) {
        buf[i] = rand() % 256;  // 填充随机字节
    }
}

// 异步写入文件
void async_write(struct io_uring *ring, int fd, char *buf, size_t size) {
    struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
    if (!sqe) {
        fprintf(stderr, "Failed to get SQE\n");
        exit(EXIT_FAILURE);
    }

    io_uring_prep_write(sqe, fd, buf, size, 0);  // 异步写入
    io_uring_sqe_set_data(sqe, buf);             // 关联缓冲区(用于后续释放)

    io_uring_submit(ring);  // 提交请求
}

int main() {
    struct io_uring ring;
    int fd;
    char *buf;
    size_t size = BUF_SIZE;

    // 1. 初始化io_uring
    setup_uring(&ring, 8);  // 8个SQE(可调整)

    // 2. 创建文件并分配缓冲区
    fd = open(FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    buf = malloc(size);
    if (!buf) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    // 3. 生成随机数据并异步写入
    generate_data(buf, size);
    async_write(&ring, fd, buf, size);

    // 4. 等待写入完成
    struct io_uring_cqe *cqe;
    int ret = io_uring_wait_cqe(&ring, &cqe);
    if (ret < 0) {
        perror("io_uring_wait_cqe");
        exit(EXIT_FAILURE);
    }

    if (cqe->res < 0) {
        fprintf(stderr, "Write error: %s\n", strerror(-cqe->res));
        exit(EXIT_FAILURE);
    }

    printf("Successfully wrote %zu bytes to %s\n", size, FILE_NAME);

    // 5. 清理资源
    io_uring_cqe_seen(&ring, cqe);  // 标记CQE已处理
    io_uring_queue_exit(&ring);     // 释放io_uring
    free(buf);
    close(fd);

    return 0;
}

​2. 关键点解析​

​(1)io_uring 核心步骤​

  1. ​初始化 io_uring
    • io_uring_queue_init():创建环形队列(SQ/CQ)。
    • 参数 entries 控制队列大小(影响并发能力)。
  2. ​提交异步写入请求​
    • io_uring_get_sqe():获取一个空闲的提交队列项(SQE)。
    • io_uring_prep_write():设置异步写入操作。
    • io_uring_submit():提交请求到内核。
  3. ​等待完成事件​
    • io_uring_wait_cqe():阻塞等待完成事件(CQE)。
    • 检查 cqe->res 确认写入是否成功。
  4. ​资源释放​
    • io_uring_cqe_seen():标记CQE已处理。
    • io_uring_queue_exit():释放 io_uring 资源。

​(2)性能优化建议​

  • ​缓冲区对齐​​:使用 posix_memalign 分配对齐的内存(减少内核拷贝开销)。 posix_memalign((void**)&buf, 4096, size); // 4K对齐
  • ​批量提交​​:一次性提交多个写入请求(利用 io_uring 的批处理能力)。
  • ​轮询模式​​:启用 IORING_SETUP_SQPOLL 减少系统调用(需root权限)。

​(3)扩展至64MB数据​

  • 修改 BUF_SIZE64 * 1024 * 1024
  • 如果内存不足,可分块写入(每次提交16MB,循环4次)。

​3. 编译与运行​

gcc -o io_uring_write io_uring_write.c -luring
./io_uring_write

​输出示例​​:

Successfully wrote 16777216 bytes to large_file.bin

​4. 验证写入结果​

ls -lh large_file.bin  # 检查文件大小
md5sum large_file.bin  # 验证数据完整性

​5. 总结​

组件作用
io_uring提供异步I/O接口,避免阻塞线程。
​SQE/CQE​提交队列(SQE)和完成队列(CQE)实现高效事件通知。
​缓冲区管理​大内存分配需考虑对齐和分块,避免内存碎片。

此代码适用于 ​​大文件写入、数据库日志、高性能存储​​ 等场景,通过异步I/O最大化磁盘吞吐。

此条目发表在未分类分类目录。将固定链接加入收藏夹。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注