c++怎么在Linux下利用sendfile系统调用提升文件传输效率【进阶】

夜明吖_3154

夜明吖_3154

2026-03-27

311人浏览

原创

sendfile能省用户态拷贝是因为内核直接在两个fd间搬运数据,绕过cpu拷贝和用户内存;其使用需满足源fd为普通文件、目标fd为socket等条件,且不支持数据修改。

c++怎么在linux下利用sendfile系统调用提升文件传输效率【进阶】

sendfile 系统调用为什么能省掉用户态拷贝

因为 sendfile 让内核直接在两个文件描述符之间搬运数据,不经过用户空间内存。传统 read+write 要把数据从磁盘读到用户缓冲区(一次 DMA 拷贝 + 一次 CPU 拷贝),再从用户缓冲区写到 socket(又是一次 CPU 拷贝 + 一次 DMA 拷贝)。而 sendfile 最多只触发两次 DMA 拷贝(磁盘 → 内核页缓存 → 网卡),中间完全绕过 CPU 拷贝和用户内存分配。

但前提是:源 fd 必须是普通文件(支持 mmap),目标 fd 必须是 socket 或另一个支持 splice 的 fd;且不能对数据做任何修改(比如加 header、加密、压缩)——它不是万能加速器,只是零拷贝传输的特化路径。

Linux 下 C++ 调用 sendfile 的正确姿势

别直接裸写系统调用,用封装好的 sendfile 函数(来自 <sys></sys>),注意参数顺序和返回值语义:

  • sendfile 的第 2 个参数是源 fd(必须是 seekable file,如普通文件;不能是 pipe、socket、/proc 文件)
  • 第 3 个参数是目标 fd(通常是 socket,也支持其他支持 write 的 fd)
  • 第 4 个参数是 offset 指针:传入非空指针时,它会自动更新偏移;传 nullptr 表示从当前文件位置开始,且不更新源文件 offset(适合多线程共享 fd 场景)
  • 返回值是实际传输字节数,可能小于请求长度(比如 socket 缓冲区满、被信号中断),必须检查并重试

示例关键片段:

C++14
C++14

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

下载
#include <sys>
ssize_t n = sendfile(sockfd, file_fd, &offset, count);
if (n == -1) {
    if (errno == EAGAIN || errno == EWOULDBLOCK) {
        // 非阻塞 socket 写满,需等待可写事件
    } else if (errno == EINTR) {
        // 信号中断,可重试
    }
} else if (n 

<h3>常见失败原因和对应处理</h3>
<p><code>sendfile</code> 失败不等于 bug,多数是环境或用法不匹配:</p>
<ul>
<li>源 fd 是 <code>/dev/zero</code>、<code>pipe</code>、<code>socket</code>:直接返回 <code>EINVAL</code> —— 它只认普通文件(<code>S_ISREG(st.st_mode)</code> 为真)</li>
<li>目标 fd 是普通文件(非 socket):某些旧内核不支持,或返回 <code>EINVAL</code>;新内核支持,但无性能优势</li>
<li>跨文件系统复制(比如 ext4 → xfs):部分内核版本会退化成 <code>read/write</code> 模拟,仍能工作但失去零拷贝意义</li>
<li>使用了 <code>O_DIRECT</code> 打开源文件:禁止 <code>sendfile</code>,返回 <code>EINVAL</code> —— 因为它依赖 page cache</li>
<li>目标 socket 关闭或出错:返回 <code>EPIPE</code> 或 <code>ECONNRESET</code>,需及时清理连接</li>
</ul>
<h3>sendfile 在高并发服务中的实际取舍</h3>
<p>它快,但不是“开箱即用”的银弹:</p>
<ul>
<li>无法与 TLS/SSL 共存:OpenSSL 的 <code>SSL_write</code> 不接受内核零拷贝数据,必须先解密/加密,所以 HTTPS 服务里基本用不上</li>
<li>难以做流控:你不能在传输中途插入逻辑(比如限速、日志、断点续传校验),所有控制都得放在调用前或后</li>
<li>大文件分片时要注意:单次 <code>sendfile</code> 最大长度受 <code>SSIZE_MAX</code> 和 socket 缓冲区限制,通常建议单次不超过 1MB,避免阻塞过久</li>
<li>配合 <code>epoll</code> 使用时,要监听目标 socket 的 <code>EPOLLOUT</code> 事件,而不是一上来就狂发 —— 否则大量 <code>EAGAIN</code>
</li>
</ul>
<p>真正影响性能的,往往不是单次 <code>sendfile</code> 调用本身,而是你怎么组织它的调用时机、如何应对部分成功、以及是否让整个 I/O 路径适配这种“无缓冲”模型。</p></sys>

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

相关文章

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

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

下载

相关标签:

c++

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

相关专题

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

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

2026.04.23

339

31

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

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

2023.08.10

3978

6

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

2025.12.24

1109

20

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

2026.01.21

383

30

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

2026.01.21

539

24

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

389

20

C++多线程并发控制与线程安全设计实践
C++多线程并发控制与线程安全设计实践

本专题围绕 C++ 在高性能系统开发中的并发控制技术展开,系统讲解多线程编程模型与线程安全设计方法。内容包括互斥锁、读写锁、条件变量、原子操作以及线程池实现机制,同时结合实际案例分析并发竞争、死锁避免与性能优化策略。通过实践讲解,帮助开发者掌握构建稳定高效并发系统的关键技术。

2026.03.16

213

22

Java 多线程与并发编程实战
Java 多线程与并发编程实战

深入讲解 Java 并发编程体系,涵盖 Thread / Runnable / Callable 线程创建方式、线程生命周期与状态转换、synchronized 同步锁与 Lock/ReentrantLock 显式锁、volatile 可见性保证、ThreadPool 线程池配置与调优(核心参数/拒绝策略)、JUC 并发工具类(CountDownLatch/CyclicBarrier/Semaphore/ConcurrentHashMa

2026.04.17

329

31

C++ 多线程使用教程大全
C++ 多线程使用教程大全

系统讲解 C++11 及后续标准引入的多线程编程能力,涵盖 std::thread 线程创建与生命周期管理、std::mutex / shared_mutex 互斥锁与读写锁、std::condition_variable 条件变量同步、std::atomic 原子操作与内存序(memory_order)、std::future / promise / async 异步任务、线程池的设计与实现、死锁检测与避免策略,帮助开发者编写正确高效

2026.04.28

196

17

热门下载

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

精品课程

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

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

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

共0课时 | 0人学习