深度好文

深入剖析Linux IO原理和几种零拷贝机制的实现 - 知乎
10.零拷贝原理MQCloud的专栏-CSDN博客零拷贝原理

三种IO方式【中断、DMA】

轮询

中断

零拷贝 - 图1

  1. 用户进程发起数据读取请求
  2. 系统调度为该进程分配cpu
  3. cpu向io控制器(ide,scsi)发送io请求
  4. 用户进程等待io完成,让出cpu
  5. 系统调度cpu执行其他任务
  6. 数据写入至io控制器的缓冲寄存器
  7. 缓冲寄存器满了向cpu发出中断信号
  8. cpu读取数据至内存【先拷贝到内核缓冲区,再拷贝到用户缓冲区

    DMA

    零拷贝 - 图2

  9. 用户进程发起数据读取请求

  10. 系统调度为该进程分配cpu
  11. cpu向DMA发送io请求
  12. 用户进程等待io完成,让出cpu
  13. 系统调度cpu执行其他任务
  14. 数据写入至io控制器的缓冲寄存器
  15. DMA不断获取缓冲寄存器中的数据(需要cpu时钟)
  16. 传输至内存(需要cpu时钟)
  17. 所需的全部数据获取完毕后向cpu发出中断信号
    • DMA负责从磁盘缓冲区拷贝到内核缓冲区。
    • cpu负责内核缓冲区拷贝到用户缓冲区。

零拷贝

三种方式
3 个实现思路:

  • 用户态直接 I/O
  • 减少数据拷贝次数
  • 写时复制技术。

    文件缓冲区和 socket 缓冲区

    这里图上的内核缓冲区是文件缓冲区。

直接IO

零拷贝 - 图3
用户态直接 I/O 只能适用于不需要内核缓冲区处理的应用程序

避免内核空间到用户空间的拷贝

1. 使用 mmap + write 代替原来的 read + write 方式

零拷贝 - 图4

  • mmap 主要的用处是提高 I/O 性能,特别是针对大文件
  • mmap映射的是内核缓冲区到用户缓冲区
  • mmap 的拷贝减少了 1 次拷贝【减少两次从内核空间拷贝到用户空间,增加一个从内核空间内部的拷贝】
  • mmap也是四次上下文切换?map两次,write两次

    2. sendFile【旧】

    sendfile 只适用于将数据从文件拷贝到 socket 套接字上
    零拷贝 - 图5
    sendfile 存在的问题是用户程序不能对数据进行修改,而只是单纯地完成了一次数据传输过程。

    3. sendfile + DMA gather copy【linux 2.4】

    零拷贝 - 图6

  • Linux 2.4 版本的内核对 sendfile 系统调用进行修改,为 DMA 拷贝引入了 gather 操作。sendfile 拷贝方式不再从内核缓冲区的数据拷贝到 socket 缓冲区

    4. splice

    零拷贝 - 图7
    可以用于任意两个文件描述符中传输数据,但是它的两个文件描述符参数中有一个必须是管道设备。

    写时复制

    每个进程要修改的时候才会进行拷贝,所以叫写时拷贝

    零拷贝对比

    零拷贝 - 图8

  • mmap:减少两次从内核空间拷贝到用户空间,增加一个从内核空间内部的拷贝

  • sendfile:只发起一次系统调用(2次上下文切换)
  • sendfile +DMA:不用内核空间内部拷贝了

Java中的零拷贝

  • MappedByteBuffer 是 NIO 基于内存映射(mmap)这种零拷贝方式的提供的一种实现,它继承自 ByteBuffer。FileChannel 定义了一个 map() 方法,它可以把一个文件从 position 位置开始的 size 大小的区域映射为内存映像文件。
  • DirectByteBuffer 是 MappedByteBuffer 的具体实现类
  • FileChannel.transferTo() 底层就是sendfile() 方法。
  • image.png

    MQ的零拷贝

    RocketMQ 选择了 mmap + write 这种零拷贝方式,适用于业务级消息这种小块文件的数据持久化和传输;而 Kafka 采用的是 sendfile 这种零拷贝方式,适用于系统日志消息这种高吞吐量的大块文件的数据持久化和传输。但是值得注意的一点是,Kafka 索引文件使用的是 mmap + write 方式数据文件使用的是 sendfile 方式
    零拷贝 - 图10

软中断和DMA关系

零拷贝 - 图11
image.png
图解Linux网络包接收过程 - 知乎
image.png
Linux网络 - 数据包的接收过程 - SegmentFault 思否