【Java】NIO零拷贝技术揭秘:CPU不参与的数据传输

在现代操作系统(如 Linux 2.4+ 内核)和现代网卡驱动支持下,FileChannel.transferTo在数据从内核读缓冲区网卡缓冲区 的过程中,使用的是 DMA 拷贝CPU 不参与数据搬运

核心机制:sendfile 与 Scatter/Gather

Java 的FileChannel.transferTo底层在 Linux 上依赖的是sendfile系统调用。为了实现"零拷贝",这里经历了两个阶段的演进:

早期模式

数据从磁盘读取到内核读缓冲区是 DMA 拷贝。然后,CPU 需要将数据从内核读缓冲区拷贝到内核 Socket 缓冲区。最后,再由 DMA 从 Socket 缓冲区拷贝到网卡。

这种模式下,内核读缓冲区到 Socket 缓冲区是 CPU 拷贝。

现代模式:Linux 2.4+ 及之后

这就是现在的标准实现。硬件支持了 Scatter/Gather(分散/聚集) 操作。

  1. DMA 拷贝1:磁盘控制器 -> 内核读缓冲区。CPU 无参与。
  2. CPU 拷贝(仅元数据) :CPU 只是将内核读缓冲区的文件描述符、偏移量、长度 等信息复制到 Socket 缓冲区中。注意:此时并没有复制实际的数据内容。(CPU 开销极小)
  3. DMA 拷贝2:网卡驱动读取 Socket 缓冲区中的描述符,根据描述符直接去内核读缓冲区读取数据,然后发送给网卡。

总共:2 次 DMA 拷贝(数据搬运完全由 DMA 完成),0 次 CPU 数据拷贝,2 次上下文切换。

总结

FileChannel.transferTo的实现中,数据本身从未离开过内核空间,也从未经过 CPU 的寄存器进行搬运。

  • 磁盘到内核读缓冲区:DMA 拷贝。
  • 内核读缓冲区到网卡:DMA 拷贝(依靠 Scatter/Gather 机制,网卡直接来"取"数据)。

这就是为什么它被称为"零拷贝"------指的是 CPU 拷贝次数为零

相关推荐
古法安卓3 小时前
Android-日志系统源码解析
android·java·android studio
小夏coding4 小时前
从"一把梭"到"精妙拆解" —— 滑动窗口计时框架的设计演进
java·后端
MacroZheng5 小时前
同事问我:"Claude Code经常失忆,不怕它把项目搞炸?",我:"怕,三个Markdown文件给它装个永不丢失的外置大脑!"
java·人工智能·后端
十年Java程序媛6 小时前
深度实战:JDK21 虚拟线程 + HikariCP 生产正确配比、坑点、监控全套
java·spring boot
xiaoqiMikko6 小时前
有人在搜一个不存在的 Tomcat 版本
java·tomcat
用户31268748772010 小时前
ConcurrentHashMap 怎么保证线程安全?从分段锁到 CAS+synchronized
java
vipxieliang10 小时前
ValidX vs Apache Commons Validator:功能与性能对比
java·spring boot
SimonKing10 小时前
升级Spring Boot 4后,从 Jackson 2 到 3,到底有哪些变化
java·后端·程序员
吃饱了得干活10 小时前
一篇讲清楚Spring Boot:自动装配、启动器、过滤器、拦截器、设计模式
java·spring boot·后端
lhldsg12 小时前
AI零售系统实战指南:从架构设计到落地部署全解析
java·人工智能·小程序·uni-app·零售