零拷贝详解

1、在没有DMA技术之前的I/O过程是这样的:

  • CPU发出对应的指令给磁盘控制器,然后返回
  • 磁盘控制器收到指令后,于是就开始准备数据,会把数据放入到磁盘控制器的内部缓冲区,然后产生中断
  • CPU收到中断信号后,停下手头工作,接着把磁盘控制器的缓冲区的数据一次一个字节地读进自己的寄存器。然后再把寄存器里的数据写入到内存,而在数据传输的期间CPU是无法执行其他任务 的。

在这里插入图片描述

整个传输过程中都要CPU亲自参与搬运数据的过程,而且这个过程,CPU是不能做其他事情的。这会大大降低CPU的效率,并且如果使用千兆网卡或者硬盘传输大量数据时,都用CPU搬运的话,肯定忙不过来

2、DMA技术

直接内存访问 (Direct Memory Access) ,简单理解就是,在进行I/O设备和内存的数据传输的时候,数据搬运的工作全部交给DMA控制器,而CPU不再参与任何与数据搬运相关的事情,这样CPU就可以去处理其他的事务。

在这里插入图片描述

与磁盘的交互(IO操作)都交给了DMA控制器去做,CPU得到解放

具体过程:

  • ⽤户进程调⽤ read ⽅法,向操作系统发出 I/O 请求,请求读取数据到⾃⼰的内存缓冲区中,进程进⼊阻塞状态;
  • 操作系统收到请求后,进⼀步将 I/O 请求发送 DMA ,然后让 CPU 执⾏其他任务;
  • DMA 进⼀步将 I/O 请求发送给磁盘;
  • 磁盘收到 DMA 的 I/O 请求,把数据从磁盘读取到磁盘控制器的缓冲区 中,当磁盘控制器的缓冲区被读满后,向 DMA 发起中断信号,告知⾃⼰缓冲区已满;
  • DMA 收到磁盘的信号,将磁盘控制器缓冲区中的数据拷⻉到内核缓冲区中 ,此时不占⽤ CPU,CPU 可以执⾏其他任务;
  • 当 DMA 读取了⾜够多的数据,就会发送中断信号给 CPU;
  • CPU 收到 DMA 的信号,知道数据已经准备好,于是将数据从内核拷⻉到⽤户空间 ,系统调⽤返回

早期DMA只存在于主板上,如今IO设备越来越多,数据传输的需求也不尽相同,所以每个I/O设备里面都有自己的DMA控制器

3、传统的文件传输

如果服务端要提供文件传输的功能,我们能想到的最简单的方式是:将磁盘上的文件读取出来,然后通过网络协议发送给客户端。

而传统的I/O的工作方式是,数据读取和写入是从用户空间到内核空间来回复制,而内核空间的数据是通过操作系统的I/O接口从磁盘读取或写入。

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

这两行代码干了非常多的事,如图:

在这里插入图片描述

可以看到,这期间发生了4次用户态与内核态的上下文切换 ,因为发生了两次系统调用,一次是read(),一次是write()。每一次系统调用,都要从用户态切换到内核态,等内核态完成任务后又要切换回用户态。而上下文切换的成本也很大,尤其在高并发的场景下,这类时间容易被累积放大,从而影响系统的性能。

其次,还发生了4次数据拷贝 ,两次是DMA拷贝,两次是CPU拷贝。

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

只是搬运一份数据,结果却进行了四次数据拷贝,过多的数据拷贝会消耗CPU资源,大大降低系统性能。

这种传统的文件传输存在冗余的上下文切换和拷贝次数!

优化文件传输

1、如何减少用户态与内核态的上下文切换的次数

读取磁盘数据时,之所以要发生上下文切换,这是因为用户空间没有权限操作磁盘或网卡,内核的权限最高。所以一般要通过内核去完成某些任务的时候,就需要使用操作系统提供的系统调用函数。

而一次系统调用必然会发生2次上下文切换:从用户态切换到内核态,内核态完成任务后再切换回用户态

所以要减少上下文切换的次数就要减少系统调用的次数

2、如何减少数据拷贝的次数

传统的文件传输过程会经过四次数据拷贝,而这其中,从内核的读缓冲区拷贝到用户的缓冲区中,再从用户的缓冲区拷贝到socket的缓冲区 ,这个过程是没有必要的。因为文件传输的应用场景中,在用户空间我们并不会对数据再加工 ,可以省去拷贝到数据缓冲区这一步。

零拷贝

1、实现零拷贝技术的方式通常有2种:

  • mmap+write
  • sendfile

它们是如何减少上下文切换和数据拷贝的次数?

2、mmap+write

read()系统调用的过程,会将内核缓冲区的数据拷贝到用户的缓冲区,为了减少这一步开销,我们可以用mmap()替换read()系统调用函数。

buf = mmap(file, len);
write(sockfd, buf, len);

mmap()系统调用函数会直接把内核缓冲区里的数据映射到用户空间,这样操作系统内核与用户空间就不需要再进行任何的数据拷贝操作

这样做会将内核的读缓冲区拷贝到用户缓冲区,再从用户缓冲区拷贝到socket的缓冲区 这两次拷贝变成内核缓冲区拷贝到socket缓冲区 这一次拷贝

即从原来的四次拷贝变为三次拷贝,减少了一次数据拷贝的过程。

但这并不是理想的零拷贝,因为仍然需要通过CPU把内核缓冲区的数据拷贝到socket缓冲区中,而且仍然需要4次上下文切换

3、sendfile

在Linux内核版本2.1中,提供了一个专门发送文件的系统调用函数sendfile()。

  • ⾸先,它可以替代前⾯的 read() 和 write() 这两个系统调⽤,这样就可以减少⼀次系统调⽤ ,也就减少了 2 次上下⽂切换的开销。
  • 其次,该系统调⽤,可以直接把内核缓冲区⾥的数据拷⻉到 socket 缓冲区⾥ ,不再拷⻉到⽤户态,这样就只有 2 次上下⽂切换,和 3 次数据拷⻉。

从 Linux 内核 2.4 版本开始起,对于⽀持⽹卡⽀持 SG-DMA 技术的情况下, sendfile() 系统,调⽤的过程发⽣了点变化,具体过程如下:

  • 第⼀步,通过 DMA 将磁盘上的数据拷⻉到内核缓冲区⾥;(DMA拷贝)
  • 第⼆步,缓冲区描述符和数据⻓度传到 socket 缓冲区,这样⽹卡的 SG-DMA 控制器就可以直接将内核缓存中的数据拷⻉到⽹卡的缓冲区⾥ ,此过程不需要将数据从操作系统内核缓冲区拷⻉到socket 缓冲区中,这样就减少了⼀次数据拷⻉;(SG-DMA拷贝)

所以,这个过程之中,只进行了一次系统调用(sendfile(),进⾏了 2 次数据拷⻉(磁盘到内核,内核到网卡)

这就是所谓的零拷贝技术。因为我们没有在内存层面去拷贝数据,全程没有通过CPU来搬运数据

在这里插入图片描述

4、总结

实现零拷贝技术的文件传输方式相比传统文件传输的方式,减少了2次上下文切换和数据拷贝次数。只需要进行两次上下文切换和两次数据拷贝就可以完成文件的传输。并且两次数据拷贝都不要通过CPU完成,是由DMA来完成。总体来看,零拷贝技术可以把文件传输的性能提高至少一倍以上

总结

1、早期I/O操作,内存与磁盘的数据传输的工作都是由CPU完成,此时CPU不能进行其他任务,会特别浪费CPU资源

2、为了解决这一问题,出现了DMA技术。每个I/O设备都有自己的DMA控制器,通过这个DMA 控制器,CPU 只需要告诉 DMA 控制器,我们要传输什么数据,从哪⾥来,到哪⾥去,就可以放⼼离开了。后续的实际数据传输⼯作,都会由 DMA 控制器来完成,CPU 不需要参与数据传输的⼯作。

3、传统的IO工作方式,从硬盘读取数据,通过网卡向外发送 。需要进行4次用户态与内核态之间的上下文切换,4次数据拷贝。其中2次数据拷贝发生在内核的缓冲区和对应的硬件设备(磁盘、网卡)之间,由DMA完成;2次数据拷贝发送在用户态和内核态之间,由CPU完成。这种传输方式有冗余的上下文切换次数和数据拷贝次数!

4、对于文件传输的优化,实现零拷贝。通过一次系统调用(sendfile)合并了磁盘读取(read)和网络发送(write)两个操作 ,降低了上下文切换次数;只进行了两次数据拷贝,从磁盘文件到内核缓冲区,从内核缓冲区到网卡,都是由DMA搬运,降低了数据拷贝次数

5、零拷贝技术是基于 PageCache 的,PageCache 会缓存最近访问的数据,提升了访问缓存数据的性能,同时,为了解决机械硬盘寻址慢的问题,它还协助 I/O 调度算法实现了 IO 合并与预读,这也是顺序读⽐随机读性能好的原因。这些优势,进⼀步提升了零拷⻉的性能。

6、当传输大文件时,不能使用零拷贝,因为可能由于 PageCache 被⼤⽂件占据,⽽导致「热点」小文件无法利用到 PageCache,并且大文件的缓存命中率不⾼,这时就需要使用「异步 IO + 直接 IO 」的方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/38405.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能时代的科学探索 | 《自然》评述

人工智能(AI)正越来越多地融入科学发现,以增强和加速研究,帮助科学家提出假设、设计实验、收集和解释大型数据集,并获得仅靠传统科学方法可能无法实现的洞察力。 过去十年间,AI取得了巨大的突破。其中就包括自监督学习和几何深度学…

手机的发展历史

目录 一.人类的通信方式变化 二.手机对人类通信的影响 三.手机的发展过程 四.手机对现代人的影响 一.人类的通信方式变化 人类通信方式的变化是一个非常广泛和复杂的话题,随着技术的进步和社会的发展,人类通信方式发生了许多重大的变化。下面是一些主…

应用程序运行报错:First section must be [net] or [network]:No such file or directory

应用程序报错环境: 在linux下,调用darknet训练的模型,报错:First section must be [net] or [network]:No such file or directory,并提示:"./src/utils.c:256: error: Assertion 0 failed." 如…

百日筑基篇——Pandas学习三(pyhton入门八)

百日筑基篇——Pandas学习三(pyhton入门八) 文章目录 前言一、数据排序二、字符串处理三、数据合并方法1. merge方法2. concat方法 四、分组数据统计五、数据重塑1. stack2. pivot 总结 前言 上一篇文章介绍了一下pandas库中的一些函数,而本…

MySQL数据类型

文章目录 MySQL数据类型1. 数据类型分类2. 数值类型2.1 tinyint类型2.2 bit类型2.3 小数类型2.3.1 float2.3.2 decimal 2.4 字符串类型2.4.1 char2.4.2 varchar2.4.3 char和varchar比较 2.5 日期和时间类型2.6 enum和set MySQL数据类型 1. 数据类型分类 红色标注是我主要讲解…

【QT】 QFileQFileInfo文件操作

很高兴在雪易的CSDN遇见你 ,给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文分享QT对文件的操作技术,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞关注,小易会继续努力分享,一起进步! 你的点…

商城-学习整理-高级-全文检索-ES(九)

目录 一、ES简介1、网址2、基本概念1、Index(索引)2、Type(类型)3、Document(文档)4、倒排索引机制4.1 正向索引和倒排索引4.2 正向索引4.3 倒排索引 3、相关软件及下载地址3.1 Kibana简介3.2 logstash简介…

【C++深入浅出】初识C++上篇(关键字,命名空间,输入输出,缺省参数,函数重载)

目录 一. 前言 二. 什么是C 三. C关键字初探 四. 命名空间 4.1 为什么要引入命名空间 4.2 命名空间的定义 4.3 命名空间使用 五. C的输入输出 六. 缺省参数 6.1 缺省参数的概念 6.2 缺省参数的分类 七. 函数重载 7.1 函数重载的概念 7.2 函数重载的条件 7.3 C支…

软件测试项目实战,电商业务功能测试点汇总(全覆盖)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 支付功能怎么测试…

C语言刷题训练【第11天】

大家好,我是纪宁。 今天是C语言笔试刷题训练的第11天,加油! 文章目录 1、声明以下变量,则表达式: ch/i (f*d – i) 的结果类型为( )2、关于代码的说法正确的是( )3、已知有如下各变…

使用 Visual Studio GoogleTest编写 C/C++ 单元测试——入门篇

入门教程 Visual Studio 新建 GoogleTest项目,一路选默认参数 pch.h #pragma once#include "gtest/gtest.h"int add(int a, int b);pch.cpp #include "pch.h"int add(int a, int b) {return a b; }test.cpp #include "pch.h"TES…

【广州华锐视点】AR电力职业技能培训系统让技能学习更“智慧”

随着科技的发展,教育方式也在不断地进步和创新。其中,增强现实(AR)技术的出现,为教育领域带来了全新的可能。AR电力职业技能培训系统就是这种创新教学方法的完美实践,它将虚拟与现实相结合,为学生提供了一个沉浸式的学…

【数据库】Sql Server可视化工具SSMS条件和SQL窗格以及版本信息

2023年,第34周,第1篇文章。给自己一个目标,然后坚持总会有收货,不信你试试! SQL SERVER 官方本身就有数据库可视化管理工具SSMS,所以大部分都会使用SSMS。以前版本是直接捆绑, 安装完成就自带有…

Python多线程与线程池(python线程池ThreadPoolExecutor)concurrent.futures高级别异步执行封装

文章目录 Python多线程与线程池一、Python多线程1.1 线程简介1.2 Python中的多线程1.3 GIL限制 二、线程池2.1 Python中的线程池 三、代码分析四、参考资料 Python多线程与线程池 一、Python多线程 在进行复杂的计算或处理大量数据时,可以通过创建多个线程来同时执…

Sentinel规则持久化

首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。 示例代码: 1.编写处理类 //规则持久化 public class FilePersistence implements InitFunc {Value("spring.application:n…

云原生k8s---资源限制、探针

目录 一:资源限制 1、资源限制原因 2、Pod 和 容器 的资源请求和限制 3、CPU 资源单位 4、内存 资源单位 5、事例 (1)事例一 (2)事例二 二:重启策略 1、重启策略模式 2、事例 三:探针…

Win10提醒事项如何打开?电脑上如何添加日程提醒?

有不少上班族表示自己在日常办公时,经常会忘记一些重要的事情,例如领导安排给自己的任务、会议安排、项目截止日期等。为了避免自己忘记工作事项,很多人都想要在电脑上设置提醒事项或添加日程提醒。那么Win10提醒事项如何打开呢?P…

[Leetcode] [Tutorial] 多维动态规划(未完待续)

文章目录 62. 不同路径Solution 62. 不同路径 一个机器人位于一个 m ∗ * ∗ n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。 问总共有多少条不同的路径? 示例…

【electron】electron项目创建的方式:

文章目录 【1】npm init quick-start/electron(推荐)【2】 克隆仓库,快速启动【3】 通过脚手架搭建项目【4】 手动创建项目 【Electron官网】https://www.electronjs.org/zh/docs/latest/api/app 【1】npm init quick-start/electron&#xf…

Excelize Go语言操作 Office Excel文档基础库

Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式&#xf…