零拷贝-易懂讲解

相信大家平时在学习类似Kafka,netty等技术时都会经常见到“零拷贝”这个词,也知道“零拷贝”的出现会让网络数据传输效率更高,那么,本着知其然并知其所以然的原则,今天一起来了解一下它倒是是个啥玩意儿

引言

Linux的设计哲学之一就是:对不同的操作赋予不同的执行等级,就是所谓特权的概念,即与系统相关的一些特别关键的操作必须由最高特权的程序来完成。

Intel的X86架构的CPU提供了0到3四个特权级,数字越小,特权越高,Linux操作系统中主要采用了0和3两个特权级,分别对应的就是内核态(Kernel Mode)用户态(User Mode)。

名词解释
  1. 用户态

    一般指的是CPU执行用户线程(也就是我们自己编写的程序)的状态,在这种状态下,线程可访问的资源受限;

  2. 内核态
    在此状态下,CPU可以访问任意资源,包括硬件设备;

  3. DMA

    可以理解为是CPU的帮手,在计算机组成中,执行效率从大到小依次是:CPU>内存>网卡>磁盘,如果没有DMA的介入,CPU从内存中读取数据写入到网卡缓冲区,整体的效率会被拉低到跟网卡的效率一样。有了DMA之后,CPU可以将数据写入到socket缓冲区(内核中的一块缓存),然后通知DMA去帮他执行剩余操作(DMA会从socket缓冲区读数据,然后写入到网卡);DMA将数据写完后,会通知CPU(这个过程叫中断)。

    • 所谓用户态、内核态,都是CPU的运行状态或者说一种运行模式;
    • 为了安全起见,用户态是无法直接访问磁盘数据的,换句话说,当我们的应用程序想要读取磁盘中的某个文件时,必须要从用户态切换到内核态,然后通过操作系统中本身的一些native方法来访问磁盘;
    • 再次理解引言中的描述:内核态拥有0,最高级特权,充当着磁盘数据的守卫,所有想访问磁盘数据的应用程序,都必须从用户态切换到内核态,通过内核态来拿到数据;

传统IO

请添加图片描述

​ 网络数据传输的过程无非就是从读数据->发送数据;

​ 根据上述图片,具体说说这个流程:

  1. 用户线程调用read()方法,从用户态切换到内核态,通过DMA将磁盘上的数据copy到内核缓冲区请求读取磁盘数据;

  2. 操作系统接收到请求,通过DMA(直接访问内存)讲所需的磁盘数据copy到内核缓冲区;

  3. CPU从内核态切换到用户态,将内核缓冲区的数据读取到应用程序;

  4. 应用程序通过write()方法,从用户态切换到内核态,将数据写入到socket缓冲区,再有DMA将socket缓冲区的数据copy到网卡缓冲区;

  5. CPU从内核态切换到用户态,给应用程序响应;

    从上述流程中可以看到,一次IO处理需要经过4次用户态与内核态的上下文切换以及4次Copy;多次的上下文切换和数据copy,也直接影响了IO的效率;

零拷贝

所谓零拷贝,并不是0次拷贝,而不是不需要将数据copy到用户空间;

操作系统中的sendFile()方法实现了零拷贝,java NIO中FileChannal.transferTo()实现了操作系统的sendFile;

上图:

请添加图片描述

简单说一下商户零拷贝的流程:

  1. transferTo()方法实现了sendFile(),CPU通知DMA将数据从从盘copy到内核缓冲区;
  2. DMA拷贝完成,发出中断请求(让CPU停止当前手头上的任务,处理已完成的数据),CPU将数据copy到socket缓冲区;
  3. DMA将socket缓冲区的数据coyp到网卡缓冲区;

目前,我们IO操作,只有两次上下文切换(1. 应用程序调用transferTo()方法,用户态切换到内核态;2. 写入完成响应应用程序,内核态切换到用户态);3次copy但是依旧有一次CPU拷贝过程,还有可以优化的空间吗?答案肯定有!

真正的零拷贝

Linux2.4内核中做了改进(sendfile+DMA scatter/gather),将Kernel buffer中对应的数据描述信息(内存地址,偏移量)记录到相应的socket缓冲区当中,实现了全程无CPU参与数据搬运,实现真正的零拷贝!

上图:
请添加图片描述

优化后的零拷贝过程可以看到,当数据由DMA copy到内核缓冲区后,并没有通过CPU进行数据复制,而是仅仅将内核缓冲区中的数据对应的描述信息(地址,偏移量)发送到socket缓冲区,DMA读取socket缓冲区的数据信息,再从内核缓冲区复制数据到网卡缓冲区;

整个过程中没有任何的CPU的数据搬运过程,解放了CPU;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值