零拷贝技术

发布时间:2026/5/27 2:14:16

零拷贝技术 文章目录一、用户态与内核态二、传统模式下的文件传输流程三、零拷贝技术下的解决方案1.传统 sendfile2.sendfile SG-DMA四、零拷贝技术的实际应用一、用户态与内核态在现代操作系统中为了保障系统的安全与稳定CPU 通常支持两种运行模式用户态 和 内核态。用户态用户程序运行的状态权限较低不能直接访问硬件或内核内存空间。当进程执行用户自己的代码时就处于用户态。内核态操作系统内核运行的状态拥有最高权限可以直接访问所有硬件资源如磁盘、网卡、内存等和内核空间的数据。当进程通过系统调用进入内核代码时就切换到内核态。区分用户态和内核态的主要目的是隔离保护防止用户程序的错误或恶意行为破坏系统核心。应用程序需要操作硬件或执行敏感操作时必须通过系统调用System Call请求内核代为完成。二、传统模式下的文件传输流程传统 I/O 方式中将一个文件从磁盘发送到网络例如 Web 服务器返回一个静态文件通常使用 read() write() 两个系统调用。整个过程涉及4 次上下文切换 和 4 次数据拷贝包括 2 次 CPU 拷贝和 2 次 DMA 拷贝。具体的步骤如下进程调用 read()从用户态切换到内核态第 1 次切换。内核通过 DMADirect Memory Access直接内存访问控制器将文件数据从磁盘拷贝到内核缓冲区第 1 次拷贝DMA 拷贝。CPU 将数据从内核缓冲区拷贝到用户缓冲区第 2 次拷贝CPU 拷贝。read() 返回从内核态切换回用户态第 2 次切换。进程调用 write()再次从用户态切换到内核态第 3 次切换。CPU 将数据从用户缓冲区拷贝到Socket 缓冲区第 3 次拷贝CPU 拷贝。DMA 将数据从 Socket 缓冲区拷贝到网卡进行网络传输第 4 次拷贝DMA 拷贝。write() 返回从内核态切换回用户态第 4 次切换。三、零拷贝技术下的解决方案零拷贝Zero-Copy 技术通过消除或减少 CPU 参与的数据拷贝次数大幅提升 I/O 吞吐量、降低延迟。其核心思想是让数据尽量在内核态内部直接流转避免在用户态和内核态之间来回复制。现代操作系统提供多种零拷贝机制其中最经典且效果显著的是 sendfile() 系统调用。它允许在两个文件描述符之间直接传输数据完全在内核态完成无需将数据拷贝到用户空间。1.传统 sendfile传统的 sendfile() 实现未支持 SG-DMA 或 DMA Gather Copy 的老式网卡/驱动虽然减少了上下文切换次数但仍然需要一次 CPU 拷贝结果共2 次上下文切换3 次数据拷贝其中 1 次为 CPU 拷贝。相比传统 readwrite4 次切换4 次拷贝已有明显提升但 CPU 仍需参与一次数据搬运。。其流程如下进程调用 sendfile()从用户态切换到内核态第 1 次切换。DMA 将文件数据从磁盘拷贝到内核缓冲区第 1 次拷贝DMA 拷贝。CPU 将数据从内核缓冲区拷贝到 Socket 缓冲区第 2 次拷贝CPU 拷贝。DMA 将数据从 Socket 缓冲区拷贝到网卡第 3 次拷贝DMA 拷贝。sendfile() 返回从内核态切换回用户态第 2 次切换。2.sendfile SG-DMA借助支持 DMA Gather Copy 或 SG-DMA 的网卡sendfile() 可以实现仅 2 次上下文切换 和 2 次 DMA 拷贝完全消除 CPU 拷贝进程调用 sendfile()从用户态切换到内核态第 1 次切换。DMA 将文件数据从磁盘拷贝到内核缓冲区第 1 次 DMA 拷贝。内核仅将数据的位置和长度信息文件描述符、偏移量等传递给网卡网卡通过 DMA Gather 直接从内核缓冲区读取数据并发送无需 CPU 拷贝。sendfile() 返回从内核态切换回用户态第 2 次切换。四、零拷贝技术的实际应用应用/框架使用的零拷贝技术说明Kafkasendfile / transferTo消息日志文件从磁盘发送到网络时利用零拷贝大幅提高吞吐量Kafka 官方宣传零拷贝是其高性能关键之一。RocketMQmmap write / sendfile在消息存储和同步刷盘时结合零拷贝优化文件读写性能。NettyFileRegion (基于 sendfile 或 transferTo)用于高效传输文件内容常用于 HTTP 静态文件服务、代理等。Nginxsendfile 指令开启 sendfile on; 后Nginx 在处理静态文件请求时自动使用零拷贝极大降低 CPU 占用。Apache Tomcatsendfile通过 Sendfile 端点处理大型静态资源时启用零拷贝加速。Rediswritev分散-聚集写与零拷贝思路结合在输出缓冲区处理时减少数据复制。数据库系统如 Cassandra、RocksDBsendfile, splice用于快速备份、数据迁移、日志传输。

相关新闻