c++怎么在Linux下利用sendfile实现文件到Socket的极速传输【进阶】

风晨君_7162

风晨君_7162

2026-03-24

498人浏览

原创

能,但需满足两个硬性条件:src_fd必须是支持mmap的普通文件,dst_fd必须是支持sendfile的socket(如TCP/UDP);否则内核退化为内核态复制,失去零拷贝意义。

c++怎么在linux下利用sendfile实现文件到socket的极速传输【进阶】

sendfile 系统调用在 Linux 下能直接零拷贝传文件吗?

能,但必须满足两个硬性条件:src_fd 是普通文件(且支持 mmap),dst_fd 是 socket(且底层协议栈支持 sendfile,比如 TCP/UDP);不满足时内核会自动退化成内核态复制,失去零拷贝意义。

  • 常见错误现象:sendfile 返回成功但实测速度没提升,大概率是源 fd 来自 pipe、/proc 或加密文件系统(如 ecryptfs),这些不支持 page cache 直接转发
  • 检查方法:用 strace -e trace=sendfile64 ./your_program 看是否触发了 ENOSYS 或回退到 read/write 循环(strace 里出现大量 read 和 write 调用)
  • sendfile 不支持 TLS socket —— OpenSSL 的 SSL_write 或 gnutls_record_send 无法和 sendfile 协同,加密必须在用户态做

如何正确构造 sendfile 的参数组合?

关键不是“怎么写”,而是“谁来控制偏移和长度”。Linux 的 sendfile 默认修改 src_fd 的 file offset,但 socket 不能 seek,所以你要决定是让内核帮你推进读位置,还是自己管理。

  • 如果传整个文件且不关心并发读:把 offset 设为 nullptr,内核自动从当前 offset 开始并更新它
  • 如果要分片传输或支持断点续传:传入指向 off_t* 的指针,每次调用前手动设置起始偏移,sendfile 返回后该值会被更新为实际发送结束位置
  • count 不是“尽量发这么多”,而是“最多发这么多”——遇到信号中断、socket 缓冲区满、磁盘 I/O 阻塞都会提前返回,必须循环处理
  • 别传 STDIN_FILENO 或 STDOUT_FILENO 当 src_fd —— 它们不是 seekable regular file,sendfile 直接失败返回 EINVAL

为什么用了 sendfile 还卡在 write 等待?

因为 sendfile 只解决“数据从文件到 socket buffer”的拷贝问题,不解决“socket buffer 到网卡”的阻塞。TCP 拥塞窗口小、对端接收慢、本地发送缓冲区满,都会让 sendfile 阻塞(默认阻塞 socket)。

C++14
C++14

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

下载
  • 典型表现:程序 hang 在 sendfile 调用,strace 显示 sendfile64(..., ..., ..., 1048576) = ? 卡住
  • 解法一:把 socket 设为非阻塞(fcntl(fd, F_SETFL, O_NONBLOCK)),然后检查 sendfile 返回值 —— 若为 -1 且 errno == EAGAIN || errno == EWOULDBLOCK,说明得等 POLLOUT
  • 解法二:用 SO_SNDBUF 调大 socket 发送缓冲区(setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val))),但注意内核有上限(/proc/sys/net/core/wmem_max)
  • 别忽略 TCP_NODELAY:小文件或交互场景下,Nagle 算法会攒包,关掉它(setsockopt(..., IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))可减少延迟

sendfile 和 splice 对比:什么时候该换?

splice 更底层、更灵活,但要求两端都是 pipe 或支持 splice 的 fd(如 /dev/zero、eventfd),而 sendfile 是专为“文件→socket”优化的快捷路径。

  • 如果你需要中转(比如文件 → pipe → socket),或者想绕过 page cache 做 direct I/O,splice 是唯一选择
  • sendfile 在 ext4/xfs 上稳定高效;但在 btrfs 或 overlayfs 上可能因 CoW 行为导致意外拷贝,此时 splice + open(..., O_DIRECT) 更可控
  • splice 不支持跨 mount point(比如文件在 NFS 上,socket 在本地),sendfile 同样受限 —— 这类场景只能老实用 read/write
  • 别试图用 splice 替代 sendfile 来“优化”简单文件传输 —— 多一层抽象、多一次 syscall、更难 debug

真正影响性能的往往不是 sendfile 本身,而是你有没有关掉 Nagle、设对 socket buffer、确认文件系统支持、以及是否在非阻塞模式下正确处理 EAGAIN。漏掉其中任何一个,零拷贝就只是个幻觉。

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

相关文章

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

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

下载

相关标签:

c++

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

相关专题

更多
counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.20

3628

5

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

2026.04.23

379

31

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

6547

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2728

6

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

2023.08.14

6656

4

tcp和udp的区别
tcp和udp的区别

TCP和UDP的区别,在连接性、可靠性、速度和效率、数据报大小以及适用场景等方面。本专题为大家提供tcp和udp的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.25

563

5

udp是什么协议
udp是什么协议

UDP是OSI参考模型中一种无连接的传输层协议。本专题为大家带来udp是什么协议的相关文章,免费提供给大家。

2023.08.08

3251

5

tcp和udp有什么区别
tcp和udp有什么区别

tcp和udp的区别有:1、udp是无连接的,tcp是面向连接的;2、udp是不可靠传输,tcp是可靠传输;3、udp是面向报文传输,tcp是面向字节流传输。想了解更多tcp相关的内容,可阅读本专题下面的相关文章。

2024.11.14

3869

8

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

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

2023.06.21

4390

4

热门下载

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

精品课程

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

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

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

共0课时 | 0人学习