什么是零拷贝
零拷贝技术是指计算机执行操作时,CPU
不需要先将数据从某处内存复制到另一个特定区域,并且尽可能的让CPU
少参与到复制的过程。这种技术通常用于通过网络传输文件时节省CPU
周期和内存带宽。
现在常见实现方式是CPU
将这种复制操作指定给DMA
,由DMA
来完成这个数据转移,CPU
在整个过程中只需要执行几个指令即可。
为什么需要零拷贝
需要零拷贝的原因就是在传输文件的时候,为了更大的发挥计算机的性能。使用零拷贝技术相比较普通IO技术:
- 能够使得
CPU
不参与复制过程,转而去执行其他任务; - 减少CPU上下文切换次数
- 减少用户线程升级内核态次数
想要更加深入了解整个过程,需要明白以下几个概念。
内核空间和用户空间
在计算机启动的时候,整个虚拟内存可以分为内核空间和用户空间。
- 内核空间:操作系统为内核软件预留的空间;用户线程是不允许直接对该空间操作,通过要先将自己升级为内核态才行;
- 用户空间:普通应用程序使用的虚拟内存
这里要注意到,应用程序在将磁盘某个文件复制到某个端口时,应用线程是不能自己执行去拿数据的,必须要经过内核空间去执行。
Linux的IO读写方式
计算机的IO操作大概可以分为三种:
IO
轮询- 中断操作
DMA
执行
这里我们要明白IO
轮询、中断操作方式,都是由CPU
来完成数据复制过程;而且因为IO
操作远慢于CPU
操作,所以CPU
最少要执行4次上下文切换操作。如果这台计算机频繁的执行IO
复制操作,那么它CPU
就很难有时间去执行其他任务。
而使用DMA
的话,其数据复制过程是不需要CPU
来操作,整个过程CPU
只需要执行几个指令让DMA
去干这种事。所以,这个时候CPU
最多只会执行2次上下文切换操作。
传统复制vs零拷贝
1、传统复制
应用程序想要下载某个文件时,大概需要以下几步:
- 告诉
CPU
把某个磁盘文件移到某个网络端口上; CPU
停下手里的活,让DMA
把磁盘文件读取到某个内核缓冲区空间里,然后转过头又做自己的事了;DMA
将磁盘文件移到内核缓冲区后,告诉CPU
数据准备好了;CPU
停下手里的活,让把这个内核缓冲区数据复制到用户程序的用户空间内;- 然后,应用程序告诉
CPU
把自己空间的数据复制内核缓冲区里,有一个端口会读取这个数据的; CPU
停下手里的活,把应用程序的数据复制到内核缓冲区里,然后告诉DMA
去把这个数据移到某个网络端口上;DMA
把内核缓冲区数据复制到网络端口后,告诉CPU
活已经干完了;CPU
停下手里的活,告诉应用程序刚才的活已经干完了;
2、零拷贝
零拷贝的实现方式就很多了,但有一点就是这些数据不会再复制到应用程序空间里,有些特别情况下,整个复制操作可能减少到2次就能完成上述操作。
Linux相关指令
太多了,下面链接有介绍。但还是有一个图需要介绍一下的:
其他技术实现零拷贝的方式
Java的NIO
Netty
Kafka
RocketMQ
https://zh.wikipedia.org/wiki/%E9%9B%B6%E5%A4%8D%E5%88%B6
https://zhuanlan.zhihu.com/p/83398714
https://zhuanlan.zhihu.com/p/308054212