零拷贝经常在各个框架使用,比如kafka,rocketmq,都起到了很好的作用,首先我们要知道零拷贝不是没有一次拷贝,是尽可能的减少拷贝。
我们先看看传统的数据拷贝
上面过程一共进行了4次拷贝,4次上下文切换
上面有些概念简单说明一下
用户空间和内核空间
首先我们知道我们的程序是建立在操作系统之上的,但是我的程序往往会有些动作是非常危险的,比如读写磁盘,内存读写,因此操作系统就分成了两个空间,一个用户空间,一个内核空间
上下文以及上下文切换
上下文,cpu寄存器是容量小,却速度快的一块内存,程序计数器,是记录cpu指令的东西,而我们cpu运行之前是要必须依赖cpu寄存器和程序计数器,这就是上下文
上下文切换,就是把上一个cpu的内容即寄存器和程序计算器保存起来,加载新的上下文,然后执行新的cpu任务,这就是上下文切换
虚拟内存,现在的操作系统都是使用虚拟内存,虚拟内存替代了真实的物理地址,多个虚拟内存可以指向同一个物理地址,我们可以把用户空间和内核空间的虚拟内存指向同一个物理地址,这样可以减少io操作的拷贝
DMA技术
DMA,全名Direct Memory Access,即直接内存访问,他简单来说就是帮助cpu干活的小弟,实际上他是一块对的芯片,可以允许外部设备和内存寄存器直接进行io数据传输,其过程不需要cpu参加,使用DMA技术是为了让cpu空闲起来,做其他事情,提高效率
实现零拷贝有三种方式
mmap+write,前面我们说过虚拟内存,可以把用户空间和内核空间的虚拟内存映射到同一个物理地址,而mmap就是利用这个特性,把用户缓存区和内核缓存区进行了映射,达到减少拷贝的目的,所有操作都在内存中完成
上面一共进行3次拷贝,4次上下文切换
sendfile,他是在两个个文件描述符之间传输数据,是在内存空间操作,避免了用户缓冲区和内核缓冲区的数据拷贝,
上面进行了3次数据拷贝,2次上下文切换
带有DMA拷贝功能的sendfile,linux2.4版本对sendfile进行优化,引入了SG-DMA技术,即直接可以从内存缓冲区拷贝数据到网卡,减少了数据的拷贝
上面一共发送了2次拷贝和2次上下文切换,全程没有cpu拷贝数据,真正实现了零拷贝,都是由DMA进行数据拷贝