【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 拷贝次数为零

相关推荐
像我这样帅的人丶你还15 小时前
Java 后端详解(四):分页与搜索
java·javascript·后端
她的男孩15 小时前
数据权限为什么不能只靠注解?Forge 的 Mapper 层 SQL 改写源码拆解
java·后端·架构
tntxia16 小时前
Mybatis的日志输入
java
亦暖筑序17 小时前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
用户2986985301420 小时前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao21 小时前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿21 小时前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试
鹤望兰67521 小时前
字节跳动国际支付-后端开发-三面面经
java
Flittly1 天前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
RainCity1 天前
Java Swing 自定义组件库分享(十二)
java·笔记·后端