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

相关推荐
游乐码18 小时前
c#stack
开发语言·c#
摇滚侠18 小时前
从 Vibe Coding 到 Spec Coding:研发范式演进与高质量交付
java·人工智能·ai编程
cch891818 小时前
Laravel vs 主流PHP框架:终极对决
开发语言·php·laravel
我能坚持多久18 小时前
C++类与对象(中)
开发语言·c++
江奖蒋犟18 小时前
【C++】map和set
开发语言·数据结构·c++·set·map
白杆杆红伞伞18 小时前
Qt Event
开发语言·qt
Magic--18 小时前
Qt 桌面计算器项目
开发语言·qt
李昊哲小课18 小时前
Python办公自动化教程 - 第2章 单元格样式魔法 - 让表格变得美观专业
开发语言·python·excel·openpyxl
希望永不加班18 小时前
SpringBoot 定时任务:@Scheduled 基础与动态定时
java·spring boot·后端·spring
派大星酷18 小时前
跨域是什么 有什么影响 怎么解决
java·网络