Linux磁盘IO、网络IO、零拷贝详解

一、什么是I/O?

在计算机操作系统中,所谓的I/O就是输入(input)和输出(output),也可以理解为读(read)和写(write),针对不同的对象,I/O模式可以划分为磁盘IO模型和网络IO模型

二、IO操作本质是用户空间和内核空间的转换,规则如下:

  • 内存空间分为用户空间和内核空间,也称为用户缓冲区和内核缓冲区
  • 用户的应用程序不能直接操作内核空间,需要将数据从内核空间拷贝到用户空间才能使用
  • 无论是read操作,还是write操作,都只能在内核空间里执行
  • 磁盘IO操作、网络请求加载到内存的数据一开始都是先放到内核缓冲区的

三、IO调用步骤之读(read)操作和写(write)

注:绿色的图型表示数据存储的位置,绿色的箭头则表示数据的复制

图1解析:

1、从左到右:Linux IO包含两部分,磁盘IO(Disk I/O)和网络IO(Network I/O)

2、从上到下:存储又被划分为三部分:用户空间(User space)、内核空间(Kerner space)及物理设备(Physical devices)

从上到下,为什么划分为三层?

Linux操作系统为了安全考虑,其内核管理了几乎所有的硬件设备,不允许用户进程直接访问。因此,逻辑上计算机被分为用户空间和内核空间(外设及其驱动是被划分在内核空间的)

运行在用户空间的进程就是用户态,运行在内核空间的进程就是内核态。用户态的进程,访问不了内核空间的数据,所以就需要由内核态的进程把数据拷贝到用户态。

3、缓存I/O(Buffered I/O)

3.1、磁盘IO(Disk I/O):

读操作:当应用程序调用read()方法时,操作系统检查内核缓冲区是否存在需要的数据,如果存在,那么就直接把内核空间的数据copy到用户空间,供用户的应用程序使用;如果内核缓冲区没有需要的数据,则通过DMA方式从磁盘中读取数据到内核缓冲区(DMA Copy),然后把内核空间的数据copy到用户空间(Cpu Copy)(上图绿色实线部分)

写操作:当应用程序调用write()方法时,应用程序将数据从用户空间copy到内核空间的缓冲区(如果用户空间没有相应的数据,则需要从磁盘-->内核缓冲区-->用户缓冲区依次读取),这时对用户程序来说写操作就已经完成,至于什么时候把数据再写到磁盘,由操作系统决定。操作系统将要写入磁盘的数据先保存于系统为写缓存分配的内存空间中,当保存到内存池中的数据达到一个程度时,便将数据保存在硬盘中。这样可以减少实际的磁盘操作,有效的保护磁盘免于重复的读写操作而导致的损坏,也能减少写入所需的时间。除非应用程序显式的调用了sync命令,立即把数据写入磁盘。如果应用程序没准备好写的数据,则必须先从磁盘读取数据才能执行写操作,这时会涉及到四次缓冲区的copy:

a、第一次从磁盘的缓冲区读取数据到内核缓冲区(DMA Copy);

b、第二次从内核缓冲区复制到用户缓冲区(Cpu Copy);

c、第三次从用户缓冲区写到内核缓冲区(Cpu Copy);

d、第四次从内核缓冲区写到磁盘(DMA Copy);(上图绿色实线部分双向箭头)

磁盘IO延时:

  • 寻道时间:把磁头移动到指定磁道上所经历的时间
  • 旋转延时间:指定扇区移动到磁头下面所经历的时间
  • 传输时间:数据的传输时间(数据读出或写入的时间)

Page cache 和Buffer cache:

Page cache也叫页缓冲或文件缓冲。是由好几个磁盘块构成,大小通常是4K,在64位系统上为8K。构成的几个磁盘块在物理磁盘上不一定连续,文件的组织单位为一页,也就是一个Page cache大小。Page cache是建立在文件系统(Ex4)之上的,因此其缓存的是逻辑数据。Buffer cache是建立在块层之上的,因此其缓存的是物理辑数据。Linux大约在2.4.10之后,Page cache与Buffer cache合并了

(所以图中Buffer cache是灰色的,为了更容易理解IO原理,黄色和灰色部分都可以不考虑了)

DMA(直接内存访问)方式:

DMA是一种与CPU共享内存总线的设备,它可以代替CPU,把数据从内存到设备之间进行拷贝。仅在传送一个或多个数据块的开始和结束时,才需CPU干预(发送DMA中断),整块数据的传送是在DMA的控制器的控制下完成的。

3.2、网络I/O(Network I/O)

读操作:网络IO即可以从物理磁盘中读数据,也可以从socket中读数据(从网卡中获取)。当从物理磁盘中读数据的时候,其流程和磁盘IO的读操作一样。当从socket中读数据,应用程序需要等待客户端发送数据,如果客户端还没有发送数据,对应的应用程序将会被阻塞,直接客户端发送了数据,该应用程序才会被唤醒,从Socket协议栈(即网卡)中读取客户端发送的数据到内核空间(DMA copy),然后把内核空间的数据copy到用户空间

写操作:为了简化描述,我们假设网络IO的数据从磁盘中获取,读写操作流程如下:

  • 当应用程序调用read()方法时,通过DMA方式将数据从磁盘拷贝到内核缓冲区(DMA copy);
  • 由cpu控制,将内核缓冲区的数据拷贝到用户空间的缓冲区中,供应用程序使用(CPU copy);
  • 当应用程序调用write()方法时,cpu会把用户缓冲区的数据copy到内核缓冲区的Socket Buffer中(CPU copy);
  • 最后通过DMA方式将内核空间中的Socket Buffer拷贝到Socket协议栈(即网卡设备)中传输(DMA copy);

网络IO的延时:网络IO主要延时是由服务器响应延时 + 带宽限制 + 网络延时 + 跳转路由延时 + 本地接收延时 决定。一般为几十到几千毫秒,受环境影响较大。所以一般来说,网络IO延时要大于磁盘IO延时

缓存I/O的一致性和安全性:如果出现进程死,内核死,掉电这样事件发生。数据会丢失吗?

  • 进程死:如果数据还处在application cache或clib cache的时候,数据会丢失;
  • 内核死:即使进入了page cache(完成了write),如果没有进行sync操作,数据还是会丢失;
  • 掉电:进行了sync,数据就一定写入了磁盘了吗?答案是:不一定;
  • 注意到图1中,磁盘旁边的绿色图型了吗?它表示的是磁盘上的缓存。写数据达到一个程度时才真正写入磁盘

缓存I/O的缺点:在缓存I/O机制中,DMA方式可以将数据直接从磁盘读到页缓存中,或者将数据从页缓存直接写回到磁盘上,而不能直接在应用程序地址空间和磁盘之间进行数据传输。这样的话,数据 在传输过程中需要在应用程序地址空间和页缓存之间进行多次数据拷贝操作,这些数据拷贝操作所带来的CPU以及内存开销是非常大的。对于某些特殊的应用程序来说,避开操作系统内核缓冲区,而直接在应用程序地址空间和磁盘之间传输数据,会比使用操作系统内核缓冲区获取更好的性能,因此引入"Direct I/O"。

4、直接I/O(Direct I/O)

凡是通过直接 I/O 方式进行数据传输,数据均直接在用户地址空间的缓冲区和磁盘之间直接进行传输,完全不需要页缓存的支持。

进程在打开文件的时候设置对文件的访问模式为 O_DIRECT ,这样就等于告诉操作系统进程在接下来使用 read() 或者 write() 系统调用去读写文件的时候使用的是直接 I/O 方式,所传输的数据均不经过操作系统内核缓存空间。

直接I/O优点:减少操作系统缓冲区和用户地址空间的拷贝次数。降低CPU开销和内存带宽 。对于某些应用程序来说简单是福音,将会大大提高性能。

直接I/O缺点:直接 I/O 并不总能让人如意。直接 I/O 的开销也很大,应用程序没有控制好读写,将会导致磁盘读写的效率低下。磁盘的读写是通过磁头的切换到不同的磁道上读取和写入数据,如果需要写入数据在磁盘位置相隔比较远,就会导致寻道的时间大大增加,写入读取的效率大大降低。

Direct I/O 本质是 DMA 设备把数据从用户空间拷贝到设备,或是从设备拷贝到用户空间。

5、mmap

mmap 本质是内存共享机制,它把 page cache 地址空间映射到用户空间,换句话说,mmap 是一种特殊的 Buffered I/O

offset 是文件中映射的起始位置,length 是映射的长度。

mmap内存映射原理:

mmap 内存映射过程:

    • 进程在虚拟地址空间中为映射创建虚拟映射区域。
    • 内核把文件物理地址和进程虚拟地址进行映射。
    • 进程发起对这片映射空间的访问,引发缺页异常,实现文件内容到物理内存(主存)的拷贝。
    • 换句话说,在调用 mmap 后,只是在进程的虚拟空间中分配了一段空间,真实的物理地址还不会分配的。
    • 当进程第一次访问这段空间(当作内存一样),CPU 陷入 OS 内核执行异常处理。然后异常处理会在这个时间分配物理内存,并用文件的内容填充这片内存,然后才返回进程的上下文,这时进程才会感知到这片内存里有数据。

mmap本质:

mmap 本质是内存共享机制,它把 page cache 地址空间映射到用户空间,换句话说,mmap 是一种特殊的 Buffered I/O。

因为底层有 CPU 的 MMU 支持,自然会转换到物理区域,对于进程而言是无感知。所以,磁盘数据加载到 page cache 后,用户进 程可以通过指针操作直接读写 page cache,不再需要系统调用和内存拷贝。

因此,offset 必须是按 page size 对齐的(不对齐的话就会映射失败)。

mmap 映射区域大小必须是物理页大小(page size)的整倍数(32 位系统中通常是 4k)。length 对齐是靠内核来保证的,比如文件长度是 10KB,你映射了 5KB,那么内核会将其扩充到 8KB。

6、Linux五大网络IO模型

1.BIO:阻塞模式IO

举个例子:
一个人去 商店买一把菜刀,
他到商店问老板有没有菜刀(发起系统调用)
如果有(表示在内核缓冲区有需要的数据)
老板直接把菜刀给买家(从内核缓冲区拷贝到用户缓冲区)
这个过程买家一直在等待如果没有,商店老板会向工厂下订单(IO操作,等待数据准备好)
工厂把菜刀运给老板(进入到内核缓冲区)
老板把菜刀给买家(从内核缓冲区拷贝到用户缓冲区)
这个过程买家一直在等待
是同步io

2.NIO:非阻塞模式IO

用户进程发起请求,如果数据没有准备好,那么立刻告知用户进程未准备好;此时用户进程可选择继续发起请求、或者先去做其他事情,稍后再回来继续发请求,直到被告知数据准备完毕,可以开始接收为止; 数据会由用户进程完成拷贝

举个例子:

一个人去 商店买一把菜刀,

他到商店问老板有没有菜刀(发起系统调用)

老板说没有,在向工厂进货(返回状态)

买家去别地方玩了会,又回来问,菜刀到了么(发起系统调用)

老板说还没有(返回状态)

买家又去玩了会(不断轮询)

最后一次再问,菜刀有了(数据准备好了)

老板把菜刀递给买家(从内核缓冲区拷贝到用户缓冲区)

整个过程轮询+等待:轮询时没有等待,可以做其他事,从内核缓冲区拷贝到用户缓冲区需要等待

是同步io

3.I/O多路复用模型

类似BIO,只不过找了一个代理,来挂起等待,并能同时监听多个请求; 数据会由用户进程完成拷贝

举个例子:多个人去 一个商店买菜刀,

多个人给老板打电话,说我要买菜刀(发起系统调用)

老板把每个人都记录下来(放到select中)

老板去工厂进货(IO操作)

有货了,再挨个通知买到的人,来取刀(通知/返回可读条件)

买家来到商店等待,老板把到给买家(从内核缓冲区拷贝到用户缓冲区)

多路复用:老板可以同时接受很多请求(select模型最大1024个,epoll模型),

但是老板把到给买家这个过程,还需要等待,

是同步io

select本质也是轮询最多可以监听1024个,而epoll模型是事件驱动,好了会主动告诉你

-select:小明,你写好了么?小红你写好了么?.......

-epoll:同学写好了,举手告诉老师来检查(nginx、tornado用的是epoll)windows平台不支持epoll,用的是select

4.信号驱动IO

事先发出一个请求,当有数据后会返回一个标识回调,这时你可以去请求数据(不是轮询请求,而是收到返回标识后请求)。好比银行排号,当叫到你的时候,你就可以去处理业务了(复制数据时阻塞)。

信号驱动IO,调用sigaltion系统调用,当内核中IO数据就绪时以SIGIO信号通知请求进程,请求进程再把数据从内核读入到用户空间,这一步是阻塞的

5.异步IO--AIO

发起请求立刻得到回复,不用挂起等待; 数据会由内核进程主动完成拷贝,目前不成熟

举个例子:还是买菜刀
现在是网上下单到商店(系统调用)
商店确认(返回)
商店去进货(io操作)
商店收到货把货发个卖家(从内核缓冲区拷贝到用户缓冲区)
买家收到货(指定信号)整个过程无等待
异步io

总结:

  • 同步I/O与异步I/O判断依据是,是否会导致用户进程阻塞
  • BIO中socket直接阻塞等待(用户进程主动等待,并在拷贝时也等待)
  • NIO中将数据从内核空间拷贝到用户空间时阻塞(用户进程主动询问,并在拷贝时等待)
  • IO Multiplexing中select等函数为阻塞、拷贝数据时也阻塞(用户进程主动等待,并在拷贝时也等待)
  • AIO中从始至终用户进程都没有阻塞(用户进程是被动的)

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

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

相关文章

【代码随想录——哈希表】

1.哈希表理论基础 首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。 那么哈希表能解决什么问题呢,一般哈希表都是用…

windows安装ElasticSearch以及踩坑

1.下载 elasticsearch地址:Past Releases of Elastic Stack Software | Elastichttps://www.elastic.co/cn/downloads/past-releases#elasticsearch IK分析器地址:infinilabs/analysis-ik: 🚌 The IK Analysis plugin integrates Lucene IK…

【网站项目】戒烟网站

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

【Unity Shader入门精要 第4章】数学基础(二)

1. Unity中的坐标空间 1.1 五个坐标空间 模型空间 模型自身的3D坐标系空间,左手坐标系是一个相对空间,坐标轴指向随模型旋转变化当物体有父节点时,Transform组件中各属性的值表示的即为该物体在其父物体的模型空间中的值当模型顶点传入顶点…

ICDE2024 |VDTuner:向量数据库自动调优技术

在CodeFuse接入实际业务的过程中,大模型的推理成本以及生成内容的准确性是产品规模落地的两个核心考量因素。为了降低推理成本,我们研发了CodeFuse-ModelCache语义缓存加速功能,通过引入Cache机制,缓存已经计算的结果,…

OpenCV 入门(五) —— 人脸识别模型训练与 Windows 下的人脸识别

OpenCV 入门系列: OpenCV 入门(一)—— OpenCV 基础 OpenCV 入门(二)—— 车牌定位 OpenCV 入门(三)—— 车牌筛选 OpenCV 入门(四)—— 车牌号识别 OpenCV 入门&#xf…

antdVue 自定义table列配置

最近做项目的时候需要对页面的table进行列配置的需求 子组件 <div><a-modaltitle"列配置" :visible"visible" :closable"false" :footer"null"width"800px" height"448px"><div><a-row>…

【完美解决】使用git时候出现error setting certificate verify locations: CAfile:问题

1、出现场景&#xff1a; 在使用idea的时候&#xff0c;进行git下的push&#xff0c;出现下面的错误&#xff1a; 2、原因分析&#xff1a; 可能因为重装过系统&#xff0c;或者是安装git的位置发生了变化等情况出现。 3、解决方案&#xff1a; 找到git的安装路径&#xf…

Java中Maven的依赖管理

依赖介绍 是指当前项目运行所需要的jar包&#xff0c;一个项目中可以引入多个依赖 配置 在pom.xml中编写<dependencies>标签 在<dependencies>中使用<dependency>引入标签 定义坐标的groupId、rtifactId、version 点击刷新按钮、引入新坐标 例如引入下…

运维实施工程师之Linux服务器全套教程

一、Linux目录结构 1.1 基本介绍 Linux 的文件系统是采用级层式的树状目录结构&#xff0c;在此结构中的最上层是根目录“/”&#xff0c;然后在此目录下再创建其他的目录。 在 Linux 世界里&#xff0c;一切皆文件&#xff08;即使是一个硬件设备&#xff0c;也是使用文本来标…

Android(一)

坏境 java版本 下载 Android Studio 和应用工具 - Android 开发者 | Android Developers 进入安卓官网下载 勾选协议 next 如果本地有设置文件&#xff0c;选择Config or installation folder 如果本地没有设置文件&#xff0c;选择Do not import settings 同意两个协议 耐…

接入大量设备后,视频汇聚系统EasyCVR安防监控视频融合平台是如何实现负载均衡的?

一、负载均衡 随着技术的不断进步和监控需求的日益增长&#xff0c;企业视频监控系统的规模也在不断扩大&#xff0c;接入大量监控设备已成为一项常态化的挑战。为确保企业能够有效应对这一挑战&#xff0c;视频汇聚系统EasyCVR视频融合平台凭借其卓越的高并发处理能力&#x…

Pandas入门篇(三)-------数据可视化篇3(seaborn篇)(pandas完结撒花!!!)

目录 概述一、语法二、常用单变量绘图1. 直方图&#xff08;histplot&#xff09;2. 核密度预估图&#xff08;kdeplot&#xff09;3. 计数柱状图&#xff08;countplot&#xff09; 三、常用多变量绘图1.散点图(1) scatterplot(2)regplot 散点图拟合回归线(3)jointplot 散点图…

2024年Q1脱毛膏线上市场(京东天猫淘宝)销量销额排行榜

鲸参谋监测的2024年Q1季度线上电商平台&#xff08;天猫淘宝京东&#xff09;脱毛膏行业销售数据已出炉&#xff01; 根据鲸参谋数据显示&#xff0c;今年Q1季度在线上电商平台&#xff08;天猫淘宝京东&#xff09;&#xff0c;脱毛膏的销量累计接近220万件&#xff0c;环比增…

开源代码分享(28)-含分布式光伏的配电网集群划分和集群电压协调控制

参考文献&#xff1a; [1] Chai Y , Guo L , Wang C ,et al.Network Partition and Voltage Coordination Control for Distribution Networks With High Penetration of Distributed PV Units[J].IEEE Transactions on Power Systems, 2018:3396-3407.DOI:10.1109/TPWRS.2018…

OFDM802.11a的FPGA实现(九)星座图映射(含verilog和matlab代码)

目录 1. 前言2. 调制2.1 QAM调制2.2 64-QAM 调制2.3 16-QAM 调制 3.模块实现4.Matlab仿真5.ModelSim仿真6.verilog代码 原文连接&#xff08;相关文章合集&#xff09;&#xff1a; OFDM 802.11a的xilinx FPGA实现 1. 前言 在上一篇博客当中&#xff0c;已经完成了数据域的交织…

计算机毕设

随着社会和国家的重视&#xff0c;大学对于大学生毕业设计越来越重视。 做软件设计设计方面&#xff0c;前后端分离是必不可少的&#xff0c;代码管理工具&#xff0c;前后端接口测试是项目中必须要用到的工具。做大数据设计方面&#xff0c;主要是要用到爬虫进行数据爬取&…

Unity初级---初识生命周期

1. Awake() &#xff1a;唤醒函数&#xff0c;最先执行的函数&#xff0c;只执行一次&#xff0c;当脚本文件挂载的对象被激活时调用 2. OnEnable() &#xff0c;OnDisable()&#xff1a;当脚本启用和禁用时触发&#xff0c;可执行多次&#xff0c;触发的前提是脚本挂载的对象…

奥威-金蝶BI现金流量表模板,可借鉴、可套用

企业现金流一旦出了问题都是大问题&#xff0c;会直接影响到企业的日常运作&#xff0c;甚至直接关系到企业能不能继续存活&#xff0c;因此现金流量表是企业财务分析中重要报表之一&#xff0c;也是企业监控财务监控情况的重要手段之一。那么这么重要的一份现金流量表该怎么做…

大模型模型简化机器人训练;简单易用的 3D 工具Project Neo;特斯拉放出了擎天柱机器人最新训练视频

✨ 1: DrEureka 利用大语言模型自动化将机器人仿真环境训练结果转移到真实世界 DrEureka是一种利用大型语言模型&#xff08;LLMs&#xff09;自动化和加速从仿真&#xff08;sim&#xff09;到现实世界&#xff08;real&#xff09;转移的技术。在机器人技能学习领域&#x…