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

相关推荐
爱码小白几秒前
Python 类五大方法 完整版学习笔记
开发语言·python
XiYang-DING几秒前
【Java EE】定时器
java·python·java-ee
Fuly10245 分钟前
java面试知识点复习
java·开发语言·面试
郭涤生11 分钟前
std::condition_variable的使用及主要事项
开发语言·c++
小菜鸡桃蛋狗16 分钟前
C++——list
开发语言·c++
hopetomorrow25 分钟前
学习路之PHP --PHP 常用扩展及作用表
开发语言·学习·php
信徒_29 分钟前
API 网关技术选型
java
simple-L630 分钟前
Java开发痛点技术文章大纲
java·开发语言
m0_6356474841 分钟前
Qt打包含有第三方库的软件为应用程序——CQtDeployer
开发语言·数据库·qt
simple-L61 小时前
Vue3 前端开发技术文章大纲
开发语言