零拷贝是什么?

零拷贝

  • 1. 无DMA控制器传输方式:
  • 2. DMA技术:
  • 3. 有DMA控制器传输方式:
  • 4. 服务端提供文件传输功能
    • 1)那么传统文件传输方式是什么?
    • 2)如何优化文件传输性能?
    • 3)如何实现零拷贝(避免 CPU 进行不必要的数据拷贝)?
      • mmap()+write()
      • sendfile()
      • SG-DMA
    • 4)零拷贝项目
  • 5.PageCache的作用
  • 6.发送大文件(GB级别)用什么方式传输?
  • 7.直接I/O
  • 8.参考

1. 无DMA控制器传输方式:

  • CPU发送指令给磁盘控制器,磁盘控制器收到指令后准备数据,将数据放入磁盘控制器的内部缓冲区,产生中断。CPU收到中断信号,停下手头工作,将磁盘控制器内部缓冲区的数据读入寄存器,再从寄存器读入内存。
  • 这种方式,CPU全程参与数据搬运,且在这期间无法做其他事情。

2. DMA技术:

  • Direct Memory Access:直接内存访问。
  • I/O设备和内存的数据传输由DMA控制器完成。

3. 有DMA控制器传输方式:

  • 用户进程调用read()方法向操作系统发起I/O请求,请求读取数据到用户态的内存缓冲区。
  • 操作系统调用磁盘控制器,磁盘控制器开始处理I/O请求,然后CPU接着执行其他任务。(这一步小林coding上写错了,I/O 请求不是交给 DMA控制器再由DMA控制器交给磁盘控制器,而是直接交给磁盘控制器。)
  • 磁盘控制器将数据读入其内部缓冲区,读完或读满向DMA控制器发起中断;
  • DMA控制器将磁盘内部缓冲区的数据拷贝到内核缓冲区,然后向CPU发起中断;
  • CPU将数据从内核缓冲区拷贝到用户缓冲区,read()返回数据给用户进程。

4. 服务端提供文件传输功能

1)那么传统文件传输方式是什么?

  • 服务端作为操作系统的用户,传输文件有两次系统调用,每次都要上下文切换。
  • 调用read()从缓存读取数据的时候需从用户态切换到内核态,读完再切换回来。调用write()写入socket缓冲区的时候,也要先从用户态切换到内核态,写完再切换回来。
  • 这里涉及到2次CPU拷贝和4次上下文切换。
    零拷贝是什么?_第1张图片

2)如何优化文件传输性能?

  • 减少上下文切换次数;
  • 减少CPU拷贝次数(不将数据拷贝到用户缓冲区)。

3)如何实现零拷贝(避免 CPU 进行不必要的数据拷贝)?

mmap()+write()

  • 用mmap()取代read(),将内核缓存区的数据映射到用户空间,应用进程跟操作系统内核共享内核缓冲区,这里就避免了read()的CPU拷贝。但是发送数据时应用进程调用write(),还是需要CPU将数据从内核缓冲区拷贝到socket缓冲区。并且依然是4次上下文切换。
    在这里插入图片描述

零拷贝是什么?_第2张图片

sendfile()

  • sendfile()取代read()+write(),只需2次上下文切换,CPU直接将数据从内核缓冲区拷贝到socket缓冲区。
    零拷贝是什么?_第3张图片

SG-DMA

  • 如果网卡支持SG-DMA技术,那么首先DMA将数据读入内核缓冲区,并将描述符和数据长度传到socket缓冲区,这样SG-DMA可以直接将数据从内核缓冲区拷贝到网卡缓冲区。这才是真正的零拷贝,CPU不参与数据搬运。
    零拷贝是什么?_第4张图片

4)零拷贝项目

  • kafka
  • nginx

5.PageCache的作用

  • 缓存最近被访问的数据;
  • 预读;

6.发送大文件(GB级别)用什么方式传输?

  • 异步I/O+直接I/O
  • 大文件传输不能使用PageCache原因:
    • 占满导致其他热点小数据不能被缓存;
    • 浪费一次DMA拷贝;

7.直接I/O

  • 经过缓存的I/O叫缓存I/O,不经过缓存的I/O叫直接I/O
  • 直接I/O使用场景:
    • 1.应用程序已实现磁盘数据的缓存;
    • 2.大文件传输;
  • 直接I/O无法享受PageCache的两大优点:(这些都是为了减少磁盘操作次数)
    • 合并I/O请求:内核I/O调度算法会缓存尽可能多的I/O请求,最后合并为一个更大的I/O请求;
    • 预读;

8.参考

http://xiaolincoding.com/os/8_network_system/zero_copy.html

你可能感兴趣的:(java)