零拷贝与sendFile

零拷贝是指计算机执行IO操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,进而减少上下文切换以及CPU的拷贝时间。它是一种IO操作优化技术。

Kafka的特性之一就是高吞吐率,原因之一就是因为底层使用ZeroCopy技术,直接将磁盘无需拷贝到用户空间,而是直接将数据通过内核空间传递输出,数据并没有抵达用户空间。

1、传统IO的执行流程

传统的IO流程包括read以及write的过程

  • read:将数据从磁盘读取到内核缓存区中,在拷贝到用户缓冲区
  • write:先将数据写入到socket缓冲区中,最后写入网卡设备

传统IO的执行过程:

  1. 用户进程调用read等系统调用向操作系统发出IO请求,请求读取数据到自己的内存缓冲区中。自己进入阻塞状态,上下文切换:用户态切换到内核态
  2. 操作系统收到请求后,进一步将IO请求发送磁盘。DMA(Direct Memory Access) 控制器,将数据从磁盘拷贝到内核缓冲区,此时不占用CPU
  3. CPU把内核缓冲区数据拷贝到用户应用缓冲区上下文从内核态切换至用户态,同时read函数返回数据
  4. 应用进程通过write,发起IO调用,上下文从用户态切换至内核态
  5. CPU将缓冲区的数据拷贝到socket缓冲区
  6. DMA控制器将数据从socket缓冲区拷贝到网卡设备上下文从内核态切换至用户态,同时write数据返回 

从而得知,传统I/O经过了四次上下文切换,四次拷贝 (两次CPU拷贝,两次DMA拷贝)

2、DMA

DMA(Direct Memory Access),直接内存访问。DMA本质上是一块主板上独立的芯片,允许外设设备和内存存储器之间直接进行IO数据传输,其过程不需要CPU的参与

DMA模式下,DMA就是CPU的一个代理,它负责了一部分的拷贝工作,从而减轻了CPU的负担。DMA的优点就是:中断少,CPU负担低。

 DMA读取过程

  1. 用户进程调用read等系统调用向操作系统发出IO请求,请求读取数据到自己的内存缓冲区中。自己进入阻塞状态。
  2. 操作系统收到请求后,进一步将IO请求发送DMA。然后让CPU干别的活去。
  3. DMA进一步将IO请求发送给磁盘。
  4. 磁盘驱动器收到DMA的IO请求,把数据从磁盘读取到驱动器的缓冲中。当驱动器的缓冲区被读满后,向DMA发起中断信号告知自己缓冲区已满。
  5. DMA收到磁盘驱动器的信号,将磁盘驱动器的缓存中的数据拷贝到内核缓冲区中。此时不占用CPU。这个时候只要内核缓冲区的数据少于用户申请的读的数据,内核就会一直重复步骤3跟步骤4,直到内核缓冲区的数据足够多为止。
  6. 当DMA读取了足够多的数据,就会发送中断信号给CPU。
  7. CPU收到DMA的信号,知道数据已经准备好,于是将数据从内核拷贝到用户空间,系统调用返回。

3、传统I/0与零拷贝对比

传统I/O

  1. 文件在磁盘中数据被copy到内核缓冲区
  2. 从内核缓冲区copy到用户缓冲区
  3. 用户缓冲区copy到内核与socket套接字相关的缓冲区
  4. 数据从socket缓冲区copy到相关协议引擎发送出去

零拷贝

  1. 文件在磁盘中数据被copy到内核缓冲区
  2. 从内核缓冲区copy到内核与socket相关的缓冲区。
  3. 数据从socket缓冲区copy到相关协议引擎发送出去 

4、零拷贝实现

零拷贝并非不拷贝数据,而是减少上线文切换次数以及CPU拷贝次数;实现零拷贝的方式如下:

4.1 mmap技术

mmap利用了操作系统虚拟内存的特点特点,将内核空间和用户空间的虚拟地址映射到同一个物理地址,所以将内核中的读写缓冲区与用户空间的缓冲区进行映射,所有的IO都在内核中完成。mmap+write实现的零拷贝流程如下:

  1. 用户进程通过调用mmap方法向操作系统内核发起IO调用,上下文从用户态切换至内核态
  2. 操作系统收到请求后,进一步将IO请求发送磁盘。DMA(Direct Memory Access) 控制器,将数据从磁盘拷贝到内核缓冲区,此时不占用CPU
  3. 上下文从内核态切换回用户态,mmap方法返回
  4. 用户进程通过调用write方法向操作系统内核再次发起IO调用,上下文从用户态切换至内核态
  5. CPU将内核缓冲区的数据拷贝到socket缓冲区
  6. DMA控制器将数据从socket缓冲区拷贝到网卡设备上下文从内核态切换至用户态,同时write数据返回

mmap+write实现的零拷贝其中发生了4次上线文切换以及3次拷贝(2次DMA拷贝+1次cpu拷贝)

4.2  sendfile

sendfile表示在两个文件描述符之间传输数据,它是在操作系统内核中操作的,减少了用户态和内核态的上下文切换,去除了数据从内核缓冲区和用户缓冲区之间的拷贝操作,因此可以使用它来实现零拷贝。

sendfile零拷贝流程如下:

  1. 用户进程通过sendfile方法向操作系统发起I/O调用,上下文从用户态切换至内核态
  2. 操作系统收到请求后,进一步将IO请求发送磁盘。DMA(Direct Memory Access) 控制器,将数据从磁盘拷贝到内核缓冲区,此时不占用CPU
  3. CPU将读缓冲区中的数据拷贝到socket缓冲区
  4. DDMA控制器将数据从socket缓冲区拷贝到网卡设备上下文从内核态切换至用户态,sendfile返回

由此可知通过sendfile实现的零拷贝其中发生了2次上下文切换以及3次拷贝(2次DMA拷贝+1次cpu拷贝)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值