Reference:  https://segmentfault.com/a/1190000011989008

零拷贝是什么?

维基百科对“零拷贝”是这样描述的:

"Zero-copy" describes computer operations in which the CPU does not perform the task of copying data from one memory area to another. This is frequently used to save CPU cycles and memory bandwidth when transmitting a file over a network.

“零拷贝” 描述的是CPU不执行拷贝数据从一块内存区域到另一块区域的任务的计算机操作。它通常用于在网络上传输文件时节省CPU周期和内存带宽。简单来说,零拷贝就是一种避免 CPU 将数据从一块存储拷贝到另外一块存储的技术。

为什么需要零拷贝技术?

通常我们会有这样的需求:将本地磁盘上的一个文件通过网络发送给远端的另一个服务。在传统的I/O中,我们通过一张图来看一下操作系统都会发生什么:

  1. 发出read()系统调用,这时处理器会从用户空间切换至内核空间;

  2. 向磁盘请求数据;

  3. 通过DMA将文件从磁盘上读取到内核空间缓冲区;

  4. read()系统调用返回,将数据从内核空间缓冲区拷贝至用户空间缓冲区,这时候处理器会从内核空间切换至用户空间;

  5. 发出write()系统调用,并将数据从用户空间缓冲区拷贝至目标socket 在内核空间的缓冲区,这时候处理器会从用户空间切换至内核空间;

  6. write()调用返回;

  7. 通过DMA将数据从内核空间缓冲区中拷贝至协议引擎(该操作是独立且异步的)。

总的来说:传统的I/O操作在整个过程中将会产生4次上下文切换和4次数据拷贝。

Q:有人可能会问, 为什么write()调用会先返回,难道他会在数据传输前返回?
A:事实上调用的返回并不保证数据被传输,甚至他并不保证传输的开始,只是意味着以太网驱动程序在其传输队列中有空位,并已经接受我们的将要传输的数据。在我们之前很可能还有很多数据包在排除。除非驱动程序或硬件实现优先级环或队列,否则数据都将以先进先出的方式被传输。

了解了传统I/O的操作后,我们再来观察一下整个过程,我们会注意到第二次和第三次数据拷贝是完全没有意义的,应用程序仅仅缓存了一下数据就又原封不动的把它发送给了目标socket 缓冲区。而且这两次拷贝是需要CPU全程参与的,从操作系统的角度来说,如果 CPU 一直被占用着去执行这项简单的任务,那么这将会是很浪费资源的;如果有其他比较简单的系统部件可以代劳这件事情,从而使得 CPU 解脱出来可以做其他的事情,那么系统资源的利用则会更加有效。

“零拷贝”正是通过消除这些多余的拷贝来提升性能的。在数据传输的过程中,避免数据在内核空间缓冲区和用户空间缓冲区之间进行拷贝,以及数据在内核空间缓冲区内的CPU拷贝。


零拷贝的实现机制

Linux 中提供类似的系统调用主要有 sendfile()、mmap() 和splice()(本文对该系统调用暂不做讨论)。

通过sendfile()实现的零拷贝

sendfile系统调用在内核版本2.1中被引入,目的是简化通过网络在两个本地文件之间进行的数据传输过程。sendfile系统调用的引入,不仅减少了数据复制,还减少了上下文切换的次数。为了更好的说明,请看下图:

  1. 发出sendfile()系统调用,这时处理器会从用户空间切换至内核空间;

  2. 向磁盘请求数据;

  3. 通过DMA将文件从磁盘上读取到内核空间缓冲区;

  4. 将数据从内核空间缓冲区拷贝到目标socket缓冲区;

  5. Sendfile()返回,这时处理器从内核空间切换至用户空间;

  6. 通过DMA将数据从目标socket缓冲区拷贝至协议引擎。

总结一下这种实现,整个过程产生了2次上下文切换和3次数据拷贝(其中2次DMA拷贝和1次CPU拷贝)。

该实现虽然减少了2次上下文切换,但仍然还有1次CPU拷贝。那这次拷贝是不是也可以省掉呢?答案是肯定的。但是需要底层操作系统的一些支持。那就是带有DMA收集功能的sendfile实现的零拷贝。

带有DMA收集功能的sendfile实现的零拷贝

从Linux2.4开始,操作系统底层提供了带有scatter/gather的DMA来从内核空间缓冲区中将数据读取到协议引擎中。这就意味着等待传输的数据不需要在连续存储器中,它可以分散在不同的内存位置。那这样一来,从文件中读出的数据就不必拷贝至目标socket的缓冲区中,只需要将缓冲区描述符添加到目标socket的缓冲区中,DMA收集操作会根据缓冲区描述符中的信息将内核空间缓冲区中的数据读取到协议引擎。这种方法不仅减少了上下文切换、还减少了由CPU参与的数据拷贝。为了更好的理解这种方法所涉及的操作,请看下图:

  1. 发出sendfile()系统调用,处理器从用户空间切换至内核空间;

  2. 通过DMA将数据copy至内核空间缓冲区;

  3. 将数据在内核空间缓冲区的地址和偏移量拷贝至目标socket的缓冲区;

  4. Sendfile()返回,处理器从内核空间切换至用户空间。

  5. 带有scatter/gather 功能的DMA将数据直接从内核缓冲区读取到协议引擎,从而消除了最后一次CPU拷贝。

总结一下,这种方法产生了2次上下文切换和2次数据拷贝。

这时有人可能会问,如果我把数据从磁盘上读出来后,再编辑一下,再发送出去,以上所说的零拷贝岂不是不能实现?
对于该问题,Linux提供了mmap来实现。

通过mmap实现的零拷贝

mmap(内存映射):mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制,相比较在用户空间和内核空间互相拷贝数据,效率更高。

  1. 发出mmap()系统调用,处理器从用户空间切换至内核空间。

  2. 向磁盘请求数据;

  3. 通过DMA将数据从磁盘拷贝至内核空间缓冲区;

  4. mmap()调用返回,这时候用户程序和操作系统共享这个缓冲区,不需要再将数据从kernel buffer 拷贝至 user buffer,处理器从内核空间切换至用户空间;

  5. 用户逻辑处理;

  6. 发出write()系统调用,将数据从内核空间缓冲区拷贝至目标socket缓冲区,这时处理器从用户空间切换至内核空间;

  7. write()调用返回,处理器从内核空间切换至用户空间;

  8. 通过DMA将数据拷贝至协议引擎。

总结一下:这种方法将产生4次上下文切换和3次数据拷贝。

至此,零拷贝技术就介绍完了。本文所提及的零拷贝技术都是需要底层操作系统支持的,同时,零拷贝技术一直是在不断地发展和完善当中的,本文并没有涵盖 Linux 上出现的所有零拷贝技术。

转载于:https://www.cnblogs.com/skying555/p/11122072.html

Linux下的零拷贝相关推荐

  1. Linux 中的零拷贝技术,第 2 部分

    技术实现 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.第一部分主要介绍了一些零拷贝技术的相关背景知识,简要概 ...

  2. Linux 中的零拷贝技术

    引言 传统的 Linux 操作系统的标准 I/O 接口是基于数据拷贝操作的,即 I/O 操作会导致数据在操作系统内核地址空间的缓冲区和应用程序地址空间定义的缓冲区之间进行传输.这样做最大的好处是可以减 ...

  3. Linux网络编程 | 零拷贝 :sendfile、mmap、splice、tee

    文章目录 传统文件传输的问题 Linux中实现零拷贝的方法 传统文件传输的问题 在网络编程中,如果我们想要提供文件传输的功能,最简单的方法就是用read将数据从磁盘上的文件中读取出来,再将其用writ ...

  4. linux 下的光盘拷贝

    linux 下的光盘拷贝 mkisofs -r -o cd.iso [-m temp] burn/  将burn/ 目录下的文件生成到映像 dd if=/dev/cdrom of=cd.iso     ...

  5. Linux 操作系统原理 — 零拷贝技术

    目录 文章目录 目录 Linux I/O 缓存背景 为什么需要零拷贝? 零拷贝技术(Zero-Copy) 方法一:用户态直接 I/O 方法二:mmap + write 方法三:Sendfile 方法四 ...

  6. Linux网络处理“零拷贝”技术mmap()内核进程间通信设计8086分页管理——摆在一起来谈谈...

    Jack:最近听说了网络处理的"零拷贝"技术,觉得非常神奇,在网上查阅了很多资料.不过,并不是太明白--知其然,而不知其所以然.你能通俗地解释一下吗? 我:这是一个相对比较复杂的话 ...

  7. sendfile:Linux中的零拷贝

    如今几乎每个人都听说过Linux中所谓的"零拷贝"特性,然而我经常碰到没有充分理解这个问题的人们.因此,我决定写一些文章略微深入的讲述这个问题,希望能将这个有用的特性解释清楚.在本 ...

  8. linux 中的零拷贝技术,第 2 部分,Linux的零拷贝技术

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 不是零拷贝的情况下是如何进行的,有什么不好的地方? 一次读取磁盘文件发送到网络的数据的拷贝过程: 用户态:用户进程开辟的 ...

  9. 移动硬盘拷贝linux文件,Linux下使用移动硬盘拷贝数据

    使用移动硬盘到linux下拷贝数据 插到服务器上以后,先fdisk命令查看是否已经识别到设备 sudo fdisk –l Disk /dev/sdc : 1000.2 GB, 100020488550 ...

最新文章

  1. 统计学原理----描述性统计
  2. rs232串口驱动_电机驱动器-copley
  3. 基于VTK的MFC应用程序开发(3)
  4. 指针常量和常量指针简单区分理解
  5. linux shell $# $* $@ $?
  6. 深入了解DSP与ARM的区别与联系
  7. SVN Error: Can‘t connect to host xxxxx‘: 由于目标计算机积极拒绝,无法连接,的最快解决办法
  8. JMeter 压力测试使用CSV参数
  9. JAVA并发编程实践笔记
  10. 延迟上班别发愁,远程办公抗疫情!
  11. 前端必备Javascript 书籍测评【含红宝书和绿皮书】
  12. OPPO小布4.0:软件定义硬件,智能定义“助手”
  13. 数组的下标为什么从0开始而不是从1开始
  14. C语言中汉字的存储和输出
  15. ubuntu安装opencv viz模块
  16. Android 开发多摄像头 API
  17. ThinkPHP5_无限极分类
  18. 大数据营销更需要消费者洞察
  19. CentOS7-搭建Ftp服务
  20. react-emotion_如何使用Web Speech API和Node.js构建语音转Emotion Converter

热门文章

  1. 枚举类型是怎样定义的?有什么用途?_新型合金材料——什么是液态金属、液态金属的定义、发展以及用途...
  2. LeetCode 05最长回文子串
  3. Android中利用服务来守护进程
  4. ECMAScript6入门教程(二)
  5. C++Primer Plus (第六版)阅读笔记 + 源码分析【第四章:复合类型】
  6. spring定时器(@Scheduled)
  7. MYSQL专题-MySQL三大日志binlog、redo log和undo log
  8. 家装灯线走线图_电工装修走线图_电工装饰走线图
  9. java oscache 使用_OScache的使用(Java对象)
  10. icem密度盒怎么设置_seo中关键词密度的问题