​​io_uring实现异步大块数据到文件

​​io_uring实现异步大块数据到文件

data-ad-format="fluid" data-ad-layout-key="-7k+ex-4a-9w+4a">

相关文章:​​io_uring实现异步大块数据到文件 io_uring实现高效大文件多线程写入

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

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

​​1. 代码实现​​

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#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&#91;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_uring​​

  • io_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. 编译与运行​​

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

​​输出示例​​:

1
Successfully wrote 16777216 bytes to large_file.bin

​​4. 验证写入结果​​

1
2
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 写入文件完整代码示例

data-ad-format="auto" data-full-width-responsive="true">