零拷贝

  • 基础知识
  • 操作系统
  • 零拷贝

一、为什么需要零拷贝

如下图所示,用户进程发起read()系统调用从磁盘读取,CPU发起IO然后交由DMA,DMA将数据从磁盘缓冲区拷贝到内核缓冲区,然后CPU又将数据从内核缓冲区复制到了用户态的用户缓冲区。这中间发生了两次拷贝。

如果此时用户进程想把read进来的数据通过网络write给远方的进程了,那么流程如下图所示:

可以看到,数据从用户态拷贝到了内核态socket缓冲区,DMA又将缓冲区里的数据拷贝到了网卡。。。。

可以看到,一次read、一次write,导致了:

  • 两次系统调用
  • 两次用户态切内核态
  • 两次内核态切用户态
  • 四次数据拷贝

要想提高性能、就要减少系统调用、减少内存拷贝次数。零拷贝就是这么做的。

二、mmap + write

mmap直接将内核缓存映射到用户态的进程中(流程如下),从而避免了一次用户态到内核态的数据拷贝。

此时:

  • 两次系统调用
  • 两次用户态切内核态
  • 两次内核态切用户态
  • 三次数据拷贝

只是减少了一次拷贝。能不能减少的再多点?当然可以

三、sendfile

使用sendfile系统调用,可以让cpu直接将数据从内核缓冲区拷贝到另一个内核缓冲区,从而避免了两次系统调用

此时:

  • sendfile一次系统调用
  • 一次用户态切内核态
  • 一次内核态切用户态
  • 三次数据拷贝

四、SG-DMA

网卡支持 SG-DMA 技术,那么sendfile会在减少一次数据拷贝,数据不会再在内核态的缓冲区之间拷贝了,而是直接由SG-DMA把内核态的缓冲区里的数据拷贝至网卡的缓冲区里。如下图所示:

此时:

  • sendfile一次系统调用
  • 一次用户态切内核态
  • 一次内核态切用户态
  • 两次数据拷贝
Loading...