-
零拷贝的概念
百度百科上的解释是
计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽
这里有一个概念是“通常用于通过网络传输文件”。这个操作的一个特点是应用程序不需要对文件做任何更改。直接把文件原样通过网络发送给其他人。类似QQ发送文件的操作。
零拷贝技术可以带来下面的好处
- 节省了CPU周期,空出的CPU时间可以用来处理其他任务
- 减少了内存区域之间的数据拷贝,节省内存带宽
- 减少用户态和内核态之间的数据拷贝,提升数据传输效率
- 减少用户态和内核态之间的上下文切换
-
DMA (Direct Memory Access)—内存直接访问
先来了解下DMA的概念。传统方式下硬盘、网络、声卡这些设备和内存交换数据时是需要CPU参与的,即在CPU的指挥下传输数据。
DMA在传输数据的过程中几乎不需要CPU的参与,节省CPU的时间。
注意,DMA是在外设和内存之间直接传输数据。把一个数据从一段内存拷贝到另外一段内存是没有这种操作的。
-
传统IO数据拷贝原理
零拷贝技术是为了解决传统IO的弊端的,所以要理解零拷贝技术,先来看看传统IO的工作模式。
以一个应用程序通过网络发送文件为例
发起了两个系统调用
read(file,app_buf,len); write(socket,app_buf,len);
调用流程如下:
- JVM进程内发起read()系统调用,操作系统由用户态切换到内核态。(第一次上下文切换)
- 系统发起对硬盘数据的读取操作 DMA读取,把数据拷贝到内核read缓存区中。(第一次数据拷贝)
- 将内核read缓存区中的数据原样拷贝到应用程序缓存区中(第二次数据拷贝),同时切换回用户态(第二次上下文切换),read()系统调用完成。
- Java应用程序处理数据,发送文件的操作通常应用程序不对文件做任何处理
- JVM内发起write()系统调用,操作系统又切换回内核态(第三次上下文切换),并将应用程序缓存区的数据原样拷贝到内核socket缓存区中(第三次数据拷贝),这个区域与第一次读取文件到内核的read缓存区不是一个区域。
- write()系统调用返回,操作系统又切换回用户态(第四次上下文切换)
- 最后再通过DMA把内核socket中的数据拷贝到协议引擎中,或者直接理解为网卡中(第四次数据拷贝)
上面的读写过程一共有4次上下文切换和4次数据拷贝。
-
从上面的过程可以看出,应用程序没有对要传输的数据做任何修改。相当于做了两次无用的数据拷贝。
从内核read缓存区到应用程序缓存区
从应用程序缓存区到内核socket缓存区
零拷贝技术就是为了省去这两步操作
-
零拷贝的操作步骤
- Java NIO中的FileChannal.transferTo()会产生一个sendfile()系统调用
- 通过DMA读取数据到内核read缓存区
- 现在内核read缓存区的数据不直接拷贝到内核socket缓存区了,而是在socket缓存区追加要发送的数据在read缓存区的位置和偏移量
- DMA拷贝数据到网卡时,根据socket缓存区中的位置和偏移在read缓存中读取。
-
缓存区的作用
这里简单理解一下上面的操作中为什么要使用各种缓存区。
多个操作方对同一段数据进行操作时,由于操作的频率不一致,使用缓存区达到互不干扰提高效率的目的。
如应用程序从内核读取文件的频率和内核从磁盘读取文件的频率是不一致的,所以使用各自的缓存区。
JavaNIO(1)、零拷贝 (Zore-Copy)
最新推荐文章于 2024-07-30 15:40:41 发布