C++ 实现基于 Zero-Copy 零拷贝技术的异步大数据传输协议及其实战【源码】

落伟酱_3693

落伟酱_3693

2026-05-21

676人浏览

原创

零拷贝在c++网络传输中省去的是用户态与内核态之间重复的memcpy,典型如传统read/write路径中的“内核缓冲区→用户缓冲区→socket缓冲区”两趟cpu拷贝;sendfile/splice等系统调用可跳过用户态,直接在内核中完成fd间数据搬运。

c++ 实现基于 zero-copy 零拷贝技术的异步大数据传输协议及其实战【源码】

零拷贝在 C++ 网络传输中到底省了哪几趟 memcpy?

零拷贝不是“完全不拷贝”,而是避免用户态与内核态之间重复的 memcpy。典型场景如从磁盘读文件再发到网络,传统方式要经历:磁盘 → 内核缓冲区 → 用户缓冲区 → socket 发送缓冲区 → 网卡。Zero-Copy(如 sendfile、splice)能跳过用户态这一环,直接让内核把数据从一个 fd 搬到另一个 fd。

但 C++ 标准库不提供原生零拷贝 API,必须调用 POSIX 系统调用,且仅 Linux 支持完整能力;Windows 的 TransmitFile 语义类似,但接口和行为差异大。

  • sendfile() 适合文件 → socket,但 source fd 必须是普通文件(不支持 socket 或 pipe)
  • splice() 更灵活,支持 pipe 作为中转,可组合实现 socket-to-socket 零拷贝转发,但要求至少一端是 pipe
  • 使用前需检查内核版本(splice 在 2.6.17+ 完善,sendfile 更早)
  • 异步 I/O(如 io_uring)才能真正释放 CPU,单纯用 sendfile + 阻塞 socket 仍是同步等待

如何用 io_uring 实现真正的异步零拷贝发送?

io_uring 是 Linux 5.1+ 提供的高性能异步 I/O 接口,支持 IORING_OP_SENDFILE 和 IORING_OP_SPLICE,能把零拷贝操作提交为非阻塞任务,完成时通过 CQE 通知。

关键点不是“能不能用”,而是“怎么配才不出错”:

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载
  • 必须用 IORING_SETUP_SQPOLL(需 CAP_SYS_ADMIN)或至少启用 IORING_SETUP_IOPOLL 才能绕过 syscall 开销
  • sendfile 提交时,off 参数必须对齐文件系统块大小(常见 4K),否则返回 -EINVAL
  • 目标 socket 必须已连接且处于 non-blocking 模式,否则 io_uring 提交会失败(错误码 -EAGAIN 而非阻塞)
  • 不要在同一个 io_uring 实例里混用 read/write 和 sendfile——后者不走 page cache,若文件被 mmap 修改,可能看到脏数据

示例片段(简化):

struct iovec iov = { .iov_base = nullptr, .iov_len = 0 };
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_sendfile(sqe, sockfd, file_fd, &offset, count, 0);
io_uring_sqe_set_data(sqe, user_ctx);
io_uring_submit(&ring);

为什么 mmap + writev 有时比 sendfile 更慢?

有人尝试用 mmap 映射文件 + writev 多段发送,以为能零拷贝,实际常更差。根本原因是:mmap 只是虚拟地址映射,真正触发页加载(page fault)时仍要拷贝进 page cache;而 sendfile 可直通 page cache,甚至利用硬件 offload(如 TCP segmentation offload)。

  • mmap 后调用 writev 会强制触发缺页中断,尤其大文件首次访问时延迟尖刺明显
  • writev 本身不零拷贝——它仍要把用户态地址里的数据 copy 到 socket send buffer
  • 若文件被其他进程修改,mmap 区域可能被 kernel 重映射,导致 writev 出现 -EAGAIN 或数据错乱
  • 真正可行的替代是 IORING_OP_READV + IORING_OP_WRITEV 组合,但中间 buffer 仍在用户态,不算零拷贝

实战中容易忽略的边界条件

零拷贝协议落地最常崩在边界而非主干逻辑。比如传输 2MB 文件,99% 成功,但遇到 4097 字节就 hang 住——往往是因为没处理好 partial completion。

  • sendfile 返回值可能小于请求长度(尤其网络拥塞或接收端 RCVBUF 满),必须循环调用并更新 offset,不能只看一次返回
  • splice 对 pipe 容量敏感:默认 pipe buffer 是 64KB,若一次 splice 超过该值,会阻塞或截断,需提前 fcntl(pipefd[1], F_SETPIPE_SZ, size)
  • 文件被 truncate 时,sendfile 可能返回 -EINVAL 或静默截断,需监听 inotify 或定期 stat 校验文件大小
  • 异步场景下,io_uring 的 CQE 可能乱序完成,若依赖发送顺序(如协议头+体),必须用 IORING_F_IO_LINK 显式串行化

零拷贝的价值不在“炫技”,而在确定性低延迟和高吞吐下的资源节省。但每省一次 memcpy,就多一分对底层行为的依赖——文件系统、内核版本、socket 状态、内存页生命周期,全得亲手掐住。

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

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2228

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

999

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

427

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

307

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

406

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

580

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1389

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1197

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 181人学习

大数据(MySQL)视频教程完整版
大数据(MySQL)视频教程完整版

共200课时 | 27.7万人学习

PHP会话控制/文件上传/分页技术
PHP会话控制/文件上传/分页技术

共22课时 | 2.9万人学习