• 彻底理解零拷贝技术


    目录

    一、含义

    二、传统I/O

    三、零拷贝技术

    3.1 Sendfile技术

    3.2 splice技术

     3.3 mmap技术

    3.4 Direct I/O技术

    四、总结


    一、含义

    零拷贝(Zero-Copy)技术是一个思想,是一种 I/O 操作优化技术,可以快速高效地将数据在文件系统移动和网络接口之间传输数据,而不需要将其从内核空间复制到用户空间。

    但零拷贝并不代表一次数据复制都没有,而是尽最大可能的减少。

    实际上Zero-Copy中有一项核心技术即DMA,在IO操作中扮演十分重要的角色,具体原理不是本文范围,可自行查阅资料。

     

    二、传统I/O

    先看一个常规的IO操作,需要从磁盘中读取数据,通过网络传输出去。

    补充一个技术点

    💡 DMA技术是Direct Memory Access的缩写。其意思是“存储器直接访问”。它是指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据,既不通过CPU,也不需要CPU干预。(但注意一点:同一设备间数据copy需要CPU进行?)

    有了DMA技术之后,过程如下:

     还是 4 次数据拷贝,其中两次是 DMA 的拷贝,另外两次则是通过 CPU 拷贝:

    • 第一次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区里,这个拷贝的过程是通过 DMA 搬运的。
    • 第二次拷贝,把内核缓冲区的数据拷贝到用户的缓冲区里,于是我们应用程序就可以使用这部分数据了,这个拷贝到过程是由 CPU 完成的。
    • 第三次拷贝,把刚才拷贝到用户的缓冲区里的数据,再拷贝到内核的 socket 的缓冲区里,这个过程依然还是由 CPU 搬运的。
    • 第四次拷贝,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程又是由 DMA 搬运的。

    三、零拷贝技术

    我把零拷贝技术分为两大类,分类依据是,是否依托OS的PageCache。

    1.基于PageCache:sendfile,mmap,splice

    2.脱离PageCache:Direct I/O

    3.1 Sendfile技术

    需要硬件支持,磁盘到socket之间直接传数据,不做数据处理。

    ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
    

    sendfile技术有两个发展阶段:

    1.在Linux 2.1-2.4的版本中:1次CPU copy,2次dma copy,2次上下文切换(两次系统调用)。

     2.Linux 2.4版本后,sendfile + DMA gather copy技术组合实现2次dma copy,2次上下文切换。

    只适用于将数据从文件拷贝到 socket 套接字上的传输过程。这种技术需要硬件和驱动的支持,

     典型运用场景:kafka消费数据时,消息数据从磁盘传输到网络。

    3.2 splice技术

    Linux 在 2.6.17 版本引入 splice 系统调用,不仅不需要硬件支持,还实现了两个文件描述符之间的数据零拷贝。在 Linux 2.6.23 版本中, sendfile 机制的实现已经没有了,但是其 API 及相应的功能还在,只不过 API 及相应的功能是利用了 splice 机制来实现的。

    sendfile不同的是,splice允许任意两个文件互相连接,而并不只是文件与socket进行数据传输。对于从一个文件描述符发送数据到socket这种特例来说,一直都是使用sendfile系统调用,而splice一直以来就只是一种机制,它并不仅限于sendfile的功能。

     3.3 mmap技术

    将内核空间地址映射为用户空间地址,rw直接作用内核,保留OS的缓冲能力。

    void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize);
    

     2次上下文切换(两次系统调用),2次DMA copy,1次CPU copy。

    典型场景:Kafka生产消息落盘时,从socket直接将数据写入内核buffer。

    3.4 Direct I/O技术

    用户空间读取的文件直接与磁盘交互,没有中间 page cache 层。虽然文件的数据本身没有使用任何缓存,但是文件的元数据仍然需要缓存;MySQL 的 O_DIRECT 与 O_DIRECT_NO_FSYNC 配置是一个具体案例。

    如何使用:

    int open(const char *pathname, int flags, ... /*, mode_t mode */ );
    

    flags指定O_DIRECT。

     典型应用案例:数据库管理系统是,缓存完全自治。

    四、总结

    总结各类提升IO效能技术对比如下:

    CPU拷贝DMA拷贝系统调用上下文切换
    传统方法22read/write4
    mmap12mmap/write4
    sendfile12sendfile2
    scatter/gather copy02sendfile2
    splice02splice2
    direct I/O02open(O_DIRECT)

    DMA的2次copy都少不了,零拷贝带来是CPU copy的减少和上下文切换的减少。

  • 相关阅读:
    RESTful 接口设计
    数仓(二)
    062:mapboxGL通过jumpTo方式跳转到某位置
    总结MySQL 的一些知识点:MySQL 导出数据
    产业互联网时代,并不存在传统意义上的互联网
    Spring Cloud【实现用户鉴权(什么是JWT、JWT原理、用户微服务、JWT工具类、用户服务实现JWT鉴权)】(八)
    学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计 汉语言文学设计题材网页
    118.184.158.111德迅云安全浅谈如何避免网络钓鱼攻击
    JVM学习——1——虚拟机基础概念
    【React】React组件生命周期以及触发顺序(部分与vue做比较)
  • 原文地址:https://blog.csdn.net/feng_zi0yhv/article/details/125525854