高级IO简介

一、非阻塞IO

阻塞其实就是进入了休眠状态,交出了 CPU 控制权。
普通文件的读写操作是不会阻塞的,不管读写多少个字节数据, read() write() 一定会在有限的时间内返回,所以普通文件一定是以非阻塞的方式进行 I/O 操作,这是普通文件本质上决定的;但是对于某些文件类型,譬如上面所介绍的管道文件、设备文件等,它们既可以使用阻塞式 I/O 操作,也可以使用非阻塞式 I/O进行操作。
阻塞 I/O 与非阻塞 I/O 读文件
在调用 open() 函数打开文件时,为参数 flags 指定 O_NONBLOCK 标志, open() 调用成功后,后续的 I/O 操作将以非阻塞式方式进行;这就是非阻塞 I/O 的打开方式,如果未指定 O_NONBLOCK 标志,则默认使用阻塞式 I/O 进行操作。
阻塞 I/O 的优点与缺点
当对文件进行读取操作时,如果文件当前无数据可读,那么阻塞式 I/O 会将调用者应用程序挂起、进入休眠阻塞状态,直到有数据可读时才会解除阻塞;而对于非阻塞 I/O ,应用程序不会被挂起,而是会立即返回,它要么一直轮训等待,直到数据可读,要么直接放弃!
所以阻塞式 I/O 的优点在于能够提升 CPU 的处理效率,当自身条件不满足时,进入阻塞状态,交出 CPU资源,将 CPU 资源让给别人使用;而非阻塞式则是抓紧利用 CPU 资源,譬如不断地去轮训,这样就会导致该程序占用了非常高的 CPU 使用率。

使用非阻塞 I/O 实现并发读取
如果要先读鼠标,在接着读键盘,在实际测试当中,需要先动鼠标在按键盘(按下键盘上的按键、按完之后按下回车),这样才能既成功读取鼠标、又成功读取键盘,程序才能够顺利运行结束。因为 read 此时是阻塞式读取,先读取了鼠标,没有数据可读将会一直被阻塞,后面的读取键盘将得
不到执行。若采用轮询的非阻塞读取则可以解决这个问题。
但由于程序当中使用轮训方式,故而会使得该程序的 CPU 占用率特别高,终归还是不太安全,会对整个系统产生很大的副作用

二、I/O复用

I/O 多路复用( IO multiplexing )它通过一种机制,可以监视多个文件描述符,一旦某个文件描述符(也就是某个文件)可以执行 I/O 操作时,能够通知应用程序进行相应的读写操作。 I/O 多路复用技术是为了解决:在并发式 I/O 场景中进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程不阻塞于某个特定的I/O 系统调用。
此可知, I/O 多路复用一般用于并发式的非阻塞 I/O ,也就是多路非阻塞 I/O ,譬如程序中既要读取鼠标、又要读取键盘,多路读取。 我们可以采用两个功能几乎相同的系统调用来执行 I/O 多路复用操作,分别是系统调用 select()poll() 这两个函数基本是一样的,细节特征上存在些许差别。
I/O 多路复用存在一个非常明显的特征:外部阻塞式,内部轮询监视多路 I/O
在使用 select() poll() 时需要注意一个问题,当监测到某一个或多个文件描述符成为就绪态(可以读或写)时,需要执行相应的 I/O 操作,以清除该状态,否则该状态将会一直存在;

三、异步IO

I/O 多路复用中,进程通过系统调用 select() poll() 来主动查询文件描述符上是否可以执行 I/O 操作。
而在异步 I/O 中,当文件描述符上可以执行 I/O 操作时,进程可以请求内核为自己发送一个信号。之后进程就可以执行任何其它的任务直到文件描述符可以执行 I/O 操作为止,此时内核会发送信号给进程。
要使用异步 I/O ,程序需要按照如下步骤来执行:
通过指定 O_NONBLOCK 标志使能非阻塞 I/O
通过指定 O_ASYNC 标志使能异步 I/O
设置异步 I/O 事件的接收进程。也就是当文件描述符上可执行 I/O 操作时会发送信号通知该进程, 通常将调用进程设置为异步 I/O 事件的接收进程。
为内核发送的通知信号注册一个信号处理函数。默认情况下,异步 I/O 的通知信号是 SIGIO ,所以 内核会给进程发送信号 SIGIO
以上步骤完成之后,进程就可以执行其它任务了,当 I/O 操作就绪时,内核会向进程发送一个 SIGIO 信号,当进程接收到信号时,会执行预先注册好的信号处理函数,我们就可以在信号处理函数中进行 I/O 操作。

四、优化异步 I/O

在一个需要同时检查大量文件描述符(譬如数千个)的应用程序中,例如某种类型的网络服务端程序,与 select() poll() 相比,异步 I/O 能够提供显著的性能优势。 之所以如此,原因在于:对于异步 I/O ,内核可以“记住”要检查的文件描述符,且仅当这些文件描述符上可执行 I/O 操作时,内核才会向应用程序发送信号。
而对于 select() poll() 函数来说,内部实现原理其实是通过轮训的方式来检查多个文件描述符是否可执行 I/O 操作,所以,当需要检查的文件描述符数量较多时,随之也将会消耗大量的 CPU 资源来实现轮训检查操作。当需要检查的文件描述符并不是很多时,使用 select() poll() 是一种非常不错的方案。
现在要对上述的异步 I/O 进行优化,既然要对其进行优化,那必然存在着一些缺陷,如下所示:
默认的异步 I/O 通知信号 SIGIO 是非排队信号。 SIGIO 信号是标准信号(非实时信号、不可靠信号),所以它不支持信号排队机制,譬如当前正在执行 SIGIO 信号的处理函数,此时内核又发送 多次 SIGIO 信号给进程,这些信号将会被阻塞,只有当信号处理函数执行完毕之后才会传递给进 程,并且只能传递一次,而其它后续的信号都会丢失。
⚫ 无法得知文件描述符发生了什么事件。
优化方法:
使用实时信号替换默认信号 SIGIO
使用 sigaction() 函数注册信号处理函数;

五、存储映射 I/O

存储映射 I/O memory-mapped I/O )是一种基于内存区域的高级 I/O 操作,它能将一个文件映射到进程地址空间中的一块内存区域中,当从这段内存中读数据时,就相当于读文件中的数据(对文件进行 read 操作),将数据写入这段内存时,则相当于将数据直接写入文件中(对文件进行 write 操作)。这样就可以在不使用基本 I/O 操作函数 read() write() 的情况下执行 I/O 操作。
mmap() munmap() 函数
munmap() 解除映射
mprotect() 函数
msync() 函数

普通 I/O 与存储映射 I/O 比较

普通 I/O 方式的缺点
普通 I/O 方式一般是通过调用 read() write() 函数来实现对文件的读写,使用 read() write() 读写文件 时,函数经过层层的调用后,才能够最终操作到文件,中间涉及到很多的函数调用过程,数据需要在不同的 缓存间倒腾,效率会比较低。同样使用标准 I/O (库函数 fread() fwrite() )也是如此,本身标准 I/O 就是对普通 I/O 的一种封装。
那既然效率较低,为啥还要使用这种方式呢?原因在于,只有当数据量比较大时,效率的影响才会比较明显,如果数据量比较小,影响并不大,使用普通的 I/O 方式还是非常方便的。
存储映射 I/O 的优点
存储映射 I/O 的实质其实是共享,与 IPC 之内存共享很相似。譬如执行一个文件复制操作来说,对于普通 I/O 方式,首先需要将源文件中的数据读取出来存放在一个应用层缓冲区中,接着再将缓冲区中的数据写入到目标文件中
而对于存储映射 I/O 来说,由于源文件和目标文件都已映射到了应用层的内存区域中,所以直接操作映 射区来实现文件复制,如下所示:
首先非常直观的一点就是,使用存储映射 I/O 减少了数据的复制操作,所以在效率上会比普通 I/O 要高,其次上面也讲了,普通 I/O 中间涉及到了很多的函数调用过程,这些都会导致普通 I/O 在效率上会比存储映射 I/O 要低。
存储映射 I/O 的实质其实是共享,如何理解共享呢?其实非常简单,我们知道,应用层与内核
层是不能直接进行交互的,必须要通过操作系统提供的系统调用或库函数来与内核进行数据交互,包括操作硬件。通过存储映射 I/O 将文件直接映射到应用程序地址空间中的一块内存区域中,也就是映射区;直接将磁盘文件直接与映射区关联起来,不用调用 read() write() 系统调用,直接对映射区进行读写操作即可操作磁盘上的文件,而磁盘文件中的数据也可反应到映射区中,这就是一种共享,可以认为映射区就是应用层与内核层之间的共享内存。

存储映射 I/O 的不足

存储映射 I/O 方式并不是完美的,它所映射的文件只能是固定大小
因为文件所映射的区域已经在调用mmap()函数时通过 length 参数指定了。
另外,文件映射的内存区域的大小必须是系统页大小的整数倍
譬 如映射文件的大小为 96 字节,假定系统页大小为 4096 字节,那么剩余的 4000 字节全部填充为 0 ,虽然可以通过映射地址访问剩余的这些字节数据,但不能在映射文件中反应出来,由此可知,使用存储映射 I/O 在进行大数据量操作时比较有效;对于少量数据,使用普通 I/O 方式更加方便。

存储映射 I/O 的应用场景

由上面介绍可知,存储映射 I/O 在处理大量数据时效率高,对于少量数据处理不是很划算,所以通常来说,存储映射 I/O 会在视频图像处理方面用的比较多,譬如在  Framebuffer 编程,通俗点说就是 LCD 编程,就会使用到存储映射 I/O

六、文件锁

对于有些应用程序,进程有时需要确保只有它自己能够对某一文件进行 I/O 操作,在这段时间内不允许其它进程对该文件进行 I/O 操作。为了向进程提供这种功能,Linux 系统提供了文件锁机制。

前面学习过互斥锁、自旋锁以及读写锁,文件锁与这些锁一样,都是内核提供的锁机制,锁机制实现用于对共享资源的访问进行保护;只不过互斥锁、自旋锁、读写锁与文件锁的应用场景不一样,互斥锁、自旋锁、读写锁主要用在多线程环境下,对共享资源的访问进行保护,做到线程同步。
而文件锁,顾名思义是一种应用于文件的锁机制,当多个进程同时操作同一文件时,我们怎么保证文件 数据的正确性,linux 通常采用的方法是对文件上锁,来避免多个进程同时操作同一文件时产生竞争状态。 譬如进程对文件进行 I/O 操作时,首先对文件进行上锁,将其锁住,然后再进行读写操作;只要进程没有对文件进行解锁,那么其它的进程将无法对其进行操作;这样就可以保证,文件被锁住期间,只有它(该进程)可以对其进行读写操作。
一个文件既然可以被多个进程同时操作,那说明文件必然是一种共享资源,所以由此可知,归根结底,文件锁也是一种用于对共享资源的访问进行保护的机制,通过对文件上锁,来避免访问共享资源产生竞争状态。

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

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

相关文章

【Visual Studio 2012中文版】下载安装以及使用方法

文章目录 前言一、下载安装包二、安装步骤1.双击VS2012_ULT_chs.iso文件打开2.双击vs_ultimate.exe打开安装程序3.选择要安装的功能4.软件正在安装,请耐心等待10分钟5.安装成功,点击“启动”6.激活码(产品密钥) 三、VS2012使用&am…

CRMEB Pro版营销功能规则解读

现在,无论是中小型企业拓宽渠道,还是传统企业转型,基本都在考虑布局线上,做微商城是一大趋势,相比传统第三方电商平台,独立部署的商城系统自主性更强,功能开发也更灵活。其中,作为电…

vue3 -- 项目使用自定义字体font-family

在Vue 3项目中使用自定义字体(font-family)的方法与在普通的HTML/CSS项目中类似。可以按照以下步骤进行操作: 引入字体文件: 首先,确保你的字体文件(通常是.woff、.woff2、.ttf等格式)位于项目中的某个目录下,比如src/assets/font/。 在全局样式中定义字体: 在你的全局…

[阅读笔记25][WebArena]A Realistic Web Environment for Building Autonomous Agents

这篇论文提出了WebArena这个环境与测试基准,在24年1月发表。 之前的agent都是在一些简化过的合成环境中测试的,这会导致与现实场景脱节。这篇论文构建了一个高度逼真、可复现的环境。该环境涉及四个领域:电子商务、论坛讨论、软件开发和内容管…

多种情况下合并单元格(S-Table+Vue3)

合并单元格(S-TableVue3) 跨行合并:rowspan“合并单元格的个数” 跨列合并:colspan"“合并单元格的个数” 文章目录 合并单元格(S-TableVue3)第一列跨行合并单元格templatescript效果 多列跨行合并单元格templatescript效果图 多行合并可参考 第一列…

iOS ------ Block的总结

前面看了Block的基本知识,和一些源码。但对于block怎么用的还不了解,代码中出现block会看不懂,现在来具体看一下Block的用法并做个总结。 1.Block是什么 block对象是一个C语言结构体,可以并入C和OC的代码中,Block本质…

探索以太坊世界:使用Geth打造你的私人网络

文章目录 概要名词解释Geth(Go Ethereum)区块链网络种类 具体流程下载geth客户端配置私链新建创世区块启动私链 连接MetaMask钱包小结 概要 在区块链领域,以太坊私链的搭建是学习和开发智能合约的重要一步。私链允许开发者在独立的环境中进行…

地图图源#ESRI ArcGIS XYZ Tiles系列(TMS)

目录 1、前言 2、地图图源网址 2.1、Satellite 卫星图源 2.2、Terrain 地形图源 2.3、Street 路网/标注图源 2.4、Specifity 特色设计图源 3、专业推荐”穿搭“ 4、图源配置下载及使用 图源名称图层类别特别注意谷歌 Google①地形 ②影像 ③矢量及标注 ④特色图源国内大…

python3如何提取汉字

采用正则表达式的方法对字符串进行处理。 str1 "{我%$是,《速$.度\发》中 /国、人"(1)提取汉字 汉字的范围为”\u4e00-\u9fa5“,这个是用Unicode表示的。 import re res1 .join(re.findall([\u4e00-\u9fa…

sso-oauth2单点登录功能笔记

场景:最近公司2个系统需要做单点登录,A系统作为服务器,认证方式是sso-oauth2方式,B系统作为客户端,token方式是ta-token,先来张sso-oauth2认证方式的图 前置准备工作 第一步:要确认谁是服务提…

kubernetes的网络通信实现原理

网络原理 Kubernetes网络原理详解:一、Kubernetes 网络实现1.容器到容器(同一Pod内)通信流程:2. pod之间的通信(以Calico为例): 二、CNI 网络模型三、网络策略四、开源的容器网络方案五、 常见网…

2024年腾讯云免费服务器最新申请入口链接

腾讯云免费服务器申请入口 txybk.com/go/free 免费服务器可选轻量应用服务器和云服务器CVM,轻量配置可选2核2G3M、2核8G7M和4核8G12M,CVM云服务器可选2核2G3M和2核4G3M配置,腾讯云百科txybk.com分享2024年最新腾讯云免费服务器申请入口、限制…

【JavaEE初阶】网络原理|认识协议|协议分层|TCP/IP模型|封装和分用

一、认识协议 1.概念 简单来说:就是一种通信双方,对于通信规则的约定(标准),一定是通信双方都认可的 但是这个协议不一定是认可面非常广的,即使是两个人之间的也可叫做协议 就好⽐⻅⽹友,彼此…

(十三)C++自制植物大战僵尸游戏多用户存档实现(二)

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/8UFMs UserData.h 在头文件中定义了枚举类型openUserDataReturnType,用于表示打开用户数据文件的返回状态。FileExistError表示文件存在但是打开错误,FileExistCorrect表示文件在且正确&#xff0…

如何进行景气分析

景气分析是一种短期经济分析方法。主要分析短时间内(一般指一年内, 或几个月内)经济运行的态势,包括当前的状态和未来的趋势。景气分析可以为宏观经济政策提供重要的决策与参考信息,例如根据经济运行的方向、强弱可建议…

概念理解: DDR的寻址容量设计

主要内容:DDR寻址容量设计的概念理解示例。 DDR的数据存储在不同的bank上,你知道具体是如何通过数据总线和地址总线的配合,拿到所需的数据吗?通过下面这样一个简单的问题,我们来逐渐了解这个过程的实现。 DDR…

LeetCode 热题 100 题解:普通数组部分

文章目录 题目一:最大子数组和(No. 53)题解 题目二:合并区间(No. 56)题解 题目三:轮转数组(No. 189)题解 题目四:除自身以外数组的乘积(No. 238&a…

MySql运维篇

目录 一.日志 1.1日志分类 1.2Error Log 1.3BinaryLog 1.4SlowQuery Log 二.备份 2.1备份原因 2.2备份目标 2.3备份技术 2.3.1物理备份 2.3.2逻辑备份 2.4备份方式 2.4.1完全备份 2.4.2增量备份 2.4.3差异备份 2.5备份环境准备 2.6完全备份实验 2.6.1完全备…

https协议的加密方式详解

各位大佬能多多点赞关注评论收藏,球球各位大佬们了!! ! 目录 1.为什么要加密? 2.如何加密 1.密钥(yue,第四声) 2.对称加密 3.非对称加密 4.公证机构 3.总结 1.为什么要加密?…

趋势分析 一元线性回归及显著性检验 GIS方法 Slope

slope斜率计算公式: 假设有三年的NDVI图像 加载3年栅格数据,公式中n取3计算分子左边: 3*(1*"1990.tif"2*"1991.tif"3*"1992.tif") 计算分子右边: 6*("1990.tif""1991.tif"&q…