c++怎么在Linux下极速读取文件_io_uring异步IO实战【附源码】

云浩吖_8616

云浩吖_8616

2026-03-29

782人浏览

原创

io_uring读文件不一定比read()快,因其专为高吞吐、低延迟、大批量异步IO设计,在小文件、单次读、无并发场景下通常更慢,且需满足内核版本、O_DIRECT、内存对齐等严格条件。

c++怎么在linux下极速读取文件_io_uring异步io实战【附源码】

为什么 io_uring 读文件不一定比 read() 快

直接结论:io_uring 在小文件、单次读、无并发场景下,大概率更慢。它不是“加速器”,而是为高吞吐、低延迟、大批量异步 IO 设计的调度框架。

常见错误现象:io_uring_submit() 返回 -1、errno=ENOSYS(内核不支持),或测出来 latency 更高、CPU 占用反而飙升。

  • 必须 Linux 5.1+ 内核,且编译时启用 CONFIG_IO_URING=y(Ubuntu 20.04 默认没开,得自己装新内核)
  • 小文件(io_uring 反而多出两次内核态切换(提交 + 完成通知),不如直接 read() 一次搞定
  • 没配 IORING_SETUP_IOPOLL 或没用 IORING_OP_READ 而是绕路走 IORING_OP_READV + 分散 IO,白白增加 sqe 构造开销

怎么写一个真正能跑起来的 io_uring 文件读取最小闭环

核心不是“怎么发请求”,而是“怎么初始化、怎么等结果、怎么防崩溃”。很多示例漏掉 io_uring_queue_init() 失败检查,一运行就段错误。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 先调 io_uring_queue_init(32, &ring, IORING_SETUP_SQPOLL) —— 注意第二个参数是 struct io_uring* 指针,不是地址取值;32 是 sq 队列大小,别设太大(>256 会触发内核额外内存分配)
  • 用 io_uring_prep_read() 填充 sqe,目标 fd 必须是 O_DIRECT 打开的(否则 io_uring 会退化成同步路径),且 buffer 地址需 512 字节对齐(posix_memalign() 分配)
  • 提交后不能直接 sleep() 等,要用 io_uring_wait_cqe() + io_uring_cqe_seen() 成对处理完成事件,漏掉 cqe_seen 会导致后续 submit 失败
IORING_SETUP_SQPOLL
  • 适合:持续高频提交(>10k ops/sec)、IO 密集型服务(如 proxy、DB 存储引擎)
  • 不适合:命令行工具、单次读多个小文件、开发机测试(SMP 调度抖动大,SQPOLL 线程可能被频繁抢占)
  • 验证是否生效:ps aux | grep io_uring 应该看到类似 io_uring-sq-1234 的线程;若没看到,说明内核没启用或 init 时没传 flag

为什么读完数据却拿不到内容?对齐和缓存是隐形杀手

最常被忽略的两个点:buffer 地址没对齐 + 忘了 __builtin_ia32_clflush_opt() 或 msync() 刷 cache —— 尤其在用 O_DIRECT 时,用户空间 buffer 若在 CPU cache 里没同步,内核可能读到脏数据或直接报 -EFAULT。

  • O_DIRECT 要求 buffer 地址、offset、length 全部对齐到逻辑块大小(通常是 512B),用 posix_memalign(),别用 malloc()
  • 读完后如果立刻用 memcpy() 或打印内容,确保 buffer 已从 cache 刷出(O_DIRECT 绕过 page cache,但 CPU cache 还在);简单起见,加一句 __builtin_ia32_clflush_opt(buf)(x86)或改用 memfd_create() + mmap() 配合 MAP_SYNC(ARM64)
  • 别在 io_uring 回调里做复杂计算——它运行在内核上下文(尤其是 SQPOLL 模式),禁止调用 malloc、printf、锁等用户态函数

实际跑通的关键不在“怎么发 IO”,而在确认三件事:内核真支持、buffer 真对齐、cqe 真消费。少一个,程序就静默失败或数据错乱。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

2023.06.20

948

5

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.28

1029

10

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

2023.09.19

2007

6

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

4858

6

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

2023.06.21

4550

4

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

2023.06.29

3813

10

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

2023.06.30

3133

5

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

2023.07.05

7770

7

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

2023.07.06

7402

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习