io_uring实现异步大块数据到文件
相关文章:io_uring实现异步大块数据到文件 io_uring实现高效大文件多线程写入
使用 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 核心步骤
- 初始化 
io_uringio_uring_queue_init():创建环形队列(SQ/CQ)。- 参数 
entries控制队列大小(影响并发能力)。 
 - 提交异步写入请求
io_uring_get_sqe():获取一个空闲的提交队列项(SQE)。io_uring_prep_write():设置异步写入操作。io_uring_submit():提交请求到内核。
 - 等待完成事件
io_uring_wait_cqe():阻塞等待完成事件(CQE)。- 检查 
cqe->res确认写入是否成功。 
 - 资源释放
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_SIZE为64 * 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最大化磁盘吞吐。
io_uring 异步写入大块数据到文件, io_uring 实现异步文件写入, io_uring 16MB-64MB 数据写入, io_uring 异步IO实现代码, io_uring 大数据写入文件教程, io_uring 异步写入性能优化, io_uring 文件操作示例代码, io_uring 异步IO编程指南, io_uring 大块数据处理方法, io_uring 写入文件完整代码示例