五种常见的IO模型

news2024/7/11 11:29:30

目录

一. IO的概述

1.1 什么是IO

1.2 IO的效率问题

1.3 同步IO和异步IO的概念

二. 阻塞式IO

三. 非阻塞式IO

四. 信号驱动式IO

五. IO多路复用

六. 异步IO

七. 总结


一. IO的概述

1.1 什么是IO

IO,表示输入输出,即:InPut / OutPut,访问外部设备读取数据或者向外部设备写数据。常见的文件读写操作、网络通信操作,其实都是IO的过程。、

在Linux操作系统下,我们认为一切皆是文件,只有操作系统有权利对文件进行读和写的操作,用户如果要读写文件,本质上都是使用操作系统的文件读写接口来实现的。

这里以阻塞式读取为例,分析IO操作所进行的工作:

  • 当read/recv时,如果缓冲区中没有数据,那就阻塞式等待数据就绪 -- 等待。
  • 当read/recv时,如果缓冲区中有数据,那么就将数据从缓冲区拷贝到应用层 -- 拷贝。

因此,我们可以认为,IO = 等待 + 拷贝。只要执行流(进程/线程)参与了等待和拷贝其中之一,那么就认为这个执行流进行了IO操作。

图1.1展示了在进行文件写文件操作(input)时系统所进行的工作,可分为三步:

  1. 将文件的内容和属性信息加载到内存中去。
  2. CPU在内存中对文件内容进行修改。
  3. 将内存中被修改后的文件内容写回到内存中。
图1.1 修改磁盘文件内容的步骤

1.2 IO的效率问题

由于IO要从外设读取数据或者向外设写数据,而在计算机体系中,硬件的效率由高到低的排序是:CPU寄存器 > 高速缓存 > 内存 > 磁盘 > 网卡,对于任意的IO操作,其实大部分时间都是在等待外设数据就绪,因此效率十分低下

结论:由于IO操作消耗大量时间在等待数据就绪,因此IO的效率很低。

在互联网行业中,提高IO效率是备受关注的,结合上面的分析,高效IO和低效IO的特点为:

  • 低效IO:单位时间内,等待时间长,拷贝数据时间短。
  • 高效IO:单位时间内,拷贝数据时间长,等待数据时间短。

因此,设法降低等待时间的占比,是提高IO效率的关键所在

1.3 同步IO和异步IO的概念

在了解同步IO和异步IO之前,首先了解同步和异步的概念:

  • 同步:就是指一个调用发出后不直接返回,直到调用完成拿到结果才返回。即:发起调用的执行流(进程/线程)自身来执行调用,在调用完成时由其自身拿到结果。
  • 异步:就是指一个调用发出后马上返回,暂时先不获取调用结果。即:调用者发起调用后,其自身不执行调用的方法,而是继续执行自己本身的方法,由被调用者执行调用的方法,当被调用者执行结束后,将结果反馈给调用者。

推而广之,我们这样这样理解同步IO和异步IO:

  • 同步IO:发起IO的执行流,其本身会参与到IO的工作,即拷贝数据或等待数据就绪,并且由这个执行流本身获取到IO的结果,这种IO操作称之为同步IO。
  • 异步IO:发起IO的执行流本身不参与IO工作,而是有另外一个执行流来进行IO操作,发起IO的线程只需要等待进行IO的执行流反馈回结果即可。

二. 阻塞式IO

阻塞式IO,就是当进行读数据或写数据时,如果外设条件没有就绪,就阻塞式的等待条件就绪。如:在read/recv时,如果缓冲区中没有数据,该进程/线程就自动被添加到特定的等待队列中去等待缓冲区中被写入数据,在等待的过程中,进程/线程 不执行其它的工作。

所有的IO操作,默认都是阻塞式的,非阻塞IO需要人为进行设置

图2.1 阻塞式IO的模型图

三. 非阻塞式IO

如果一个进程/线程在进行IO操作时,数据尚未就绪,那么读取接口不会阻塞,先返回执行其他的工作,数据就绪才进行读取。

非阻塞式IO,一般采用轮询检查的方法进行IO操作,即:通过循环,不断检查IO资源是否已经就绪,就绪就读取,不就绪就执行其他的工作。

图3.1 非阻塞式IO的模型图

IO操作默认是阻塞式的,有两种方法可以实现非阻塞式IO:

  • 在使用open打开文件/调用socket接口获得fd时,传入O_NONBLOCK/SOCK_NONBLOCK作为参数,实现非阻塞式IO。
  • 通过调用fcntl函数,对指定的fd设置非阻塞式IO。

这里重点介绍如图通过调用fcntl函数来设置非阻塞式的IO。

fcntl函数 -- 对特定fd设置非阻塞IO

函数原型:int fcntl(int fd, int cmd, .../*args*/)

函数参数:

  • fd:进行操作的文件描述符。
  • cmd:F_GETFL -- 获取文件状态、F_SETFL -- 设置文件状态
  • 缺省参数:当cmd为F_SETFL时,传入O_NONBLOCK可以设置非阻塞。

返回值:当cmd为F_SETFL时,返回当前的文件状态,当cmd为F_SETFL时,应当返回0,如果函数调用失败,则返回-1。

代码3.1通过提供SetNonBlock接口,对标准输入(fd = 0)进行非阻塞式读取,在SetNonBlock内部调用fcntl函数将指定的fd设置为非阻塞。但在使用read进行非阻塞读取时,有以下几点问题需要注意:

  • 如果调用read时底层资源尚未就绪而产生非阻塞,那么read会以读取出错的形式返回。
  • read如果出错,不仅会体现在返回值上,也会设置全局错误码errno。
  • 当因为数据未就绪而非阻塞时,错误码errno被设置为EWOULDBLOCK || EAGAIN,其余为真正的读取失败。
  • 在非阻塞式read读取时,还应当判断错误码是否为EINTR,表示是否因为进程收到信号而造成read终止,如果是,应当尝试再次读取。

其中 EWOULDBLOCK 和 EAGAIN 对应的错误码都是11,描述信息为:Resource temporarily unavailable,就是资源尚未就绪的意思。

代码3.1:非阻塞式IO

#include <iostream>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>

// 设置非阻塞IO函数
bool SetNonBlockIO(int fd)
{
    // 获取文件状态
    int fd_status = fcntl(fd, F_GETFL);
    if(fd_status < 0)
    {
        // 如果失败返回false,表示设置非阻塞失败
        return false;
    }

    // 在原有的文件状态下添加非阻塞状态
    fcntl(fd, F_SETFL, fd_status | O_NONBLOCK);
    return true;
}

int main()
{
    // 对标准输入设置非阻塞
    bool ret = SetNonBlockIO(0);
    if(!ret)
    {
        exit(1);
    }

    // 开始进行非阻塞IO操作
    char buffer[1024] = { 0 };
    while(1)
    {
        ssize_t sz = read(0, buffer, 1024);
        
        // 如果正常读取
        if(sz > 0)
        {
            buffer[sz - 1] = '\0';    // 设置字符串结束标识
            std::cout << "echo# " << buffer << ", [errno:" << errno << ", errorMsg:" << strerror(errno) << "]" << std::endl;
        }
        else   // 读取失败
        {
            // 如果是因为资源没有就绪而读取失败
            if(errno == EWOULDBLOCK || errno == EAGAIN)
            {
                std::cout << "errno:" << errno << ", errorMsg:" << strerror(errno) << std::endl;
            }
            else if(errno == EINTR)   // 因为进程收到信号而终止read
            {
                std::cout << "Interrupt because of signal, errno:" << errno << ", errorMsg:" << strerror(errno) << std::endl;
            }
            sleep(1);
        }
    }

    return 0;
}

四. 信号驱动式IO

通过自定义对29号SIGIO信号的处理函数来实现信号驱动式IO,当进程收到SIGIO信号的时候,就调用对应的处理函数来进行IO操作,这样保证在调用IO接口的时候数据一定是就绪的,在没有收到信号时不影响进程进行其他的工作,信号驱动式IO避免了阻塞等待资源就绪,提高了IO效率。

图4.1 信号驱动式IO的模型图

五. IO多路复用

一个进程能够同时等待多个文件描述符的资源是否就绪,只要其中一个文件描述符的资源就绪变为可读,那么进程就会去读取这个文件描述符对应的数据。由于可以同时等待多个文件描述符,只要其中一个资源就绪,就可以进行读取,这样就大大提高了IO的效率。

图5.1 IO多路复用的模型图

六. 异步IO

异步IO,就是发起IO的执行流本身不参与IO工作,而是有另外一个执行流来进行IO操作,发起IO的线程只需要等待进行IO的执行流反馈回结果。这样发起IO的执行流就不需要等到,可以处理其他的工作。

图6.1 异步IO的模型图

七. 总结

  • IO就是对外部设备进行输入输出操作的简称,IO的效率是十分低下的。
  • IO操作在单位时间内等待资源就绪的时长越短,IO效率就越高。
  • 共有5种常见的IO模型:阻塞式IO、非阻塞式IO、信号驱动IO、IO多路复用和异步IO,其中前四种属于同步IO。
  • 同步IO和异步IO的区别在于,是否由发起IO的执行流实际执行IO操作。

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

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

相关文章

苹果15OTG音频转接器方案大卖-无敌成本加兼容性性价比直接拉满

手机拓展坞的组合有何意义&#xff1f;首先是数据存储场景&#xff0c;借助拓展坞扩展出的接口&#xff0c;可以连接U盘、移动硬盘等采用USB接口的设备&#xff0c;实现大文件的快速存储或者流转&#xff1b;其次是图片、视频的读取场景&#xff0c;想要读取相机、无人机SD/TF存…

第十周学习记录

阅读MARS MARS创新点&#xff1a; (1)实例感知。模拟器使用独立的网络分别对前景实例和背景环境进行建模&#xff0c;以便可以单独控制实例的静态&#xff08;例如大小和外观&#xff09;和动态&#xff08;例如轨迹&#xff09;属性。 (2)模块化。模拟器允许在不同的 NeRF 主干…

python操作链接数据库和Mysql中的事务在python的处理

python操作数据库 pymysql模块: pip install pymysql作用:可以实现使用python程序链接mysql数据库&#xff0c;且可以直接在python中执行sql语句 添加操作 import pymysql #1.创建链接对象c conn pymysql.Connect(host127.0.0.1,#数据库服务器主机地址port3306, #mysql的端口…

Pytest系列之参数化

1.parametrize()实现数据驱动 1.1 方法参数详解 pytest.mark.parametrize(arg_name, arg_value) arg_name:参数名称&#xff0c;用于将参数值传递给测试用例 arg_value:参数值(支持列表、字典列表、元组和字典元组)&#xff0c;有n个值&#xff0c;那么测试用例就将执行n次…

node 第十七天 使用rsa非对称加密 实现前后端加密通信 JSEncrypt和node-rsa

什么是非对称加密 加密过程需要两个钥匙, 公钥和私钥 其中公钥用于加密明文, 私钥用于解密公钥加密的密文, 解密只可以用私钥 公钥和私钥是一对一的关系 公钥可以发送给用户, 不用担心泄露 私钥需要保存在服务端, 不能泄露 例如: 战场上&#xff0c;B要给A传递一条消息&#xf…

VC6.0 高亮扩展

输入关键字 "asist vc6.0" 点击网页&#xff1a; https://wws.lanzouj.com/isNmZe9ap2f 几秒后下载成功 在VS2021 安装以下这个扩展 打开vc6.0 代码有高亮了

Python四种常见实现排序方法,干活教程分享~

文章目录 1.冒泡排序2.选择排序3.快速排序4.插入排序关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 1.冒泡排序…

软件模拟SPI协议的理解和使用编写W25Q64

SPI软件模拟的时序 SPI协议中&#xff0c;NSS、SCK、MOSI由主机产生&#xff0c;MISO由从机产生&#xff0c;在SCK每个时钟周期MOSI、MISO传输一位数据&#xff0c;数据的输入输出是同时进行的&#xff0c;所以读写数据也可以视作交换数据。所以读写时对数据位的控制都是用同一…

输出自然数-第10届蓝桥杯国赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第7讲。 输出自然数&#x…

CSS3 多媒体查询、网格布局

一、CSS3多媒体查询&#xff1a; CSS3 多媒体查询继承了CSS2多媒体类型的所有思想&#xff0c;取代了查找设备的类型。CSS3根据设置自适应显示。 多媒体查询语法&#xff1a; media not|only mediatype and (expressions) { CSS 代码...; } not: not是用来排除掉某些特定…

一文5个步骤从0到1实现Jmeter分布式压力测试(建议收藏)

之前写过用jmeter做接口测试的文章&#xff0c;本篇我们继续介绍下用jmeter做分布式压力测试的例子。 用jmeter做压力测试&#xff0c;如果只用一台机器&#xff0c;有鉴于线程数的限制和一台机器的性能&#xff0c;可能无法满足压力测试的实际需求&#xff0c;解决这个问题&a…

Postman使用json提取器和正则表达式实现接口的关联

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 一&#xff09;使用json提取器实现接口关联 实际项目场景&#xff0c;在财务信息页面&#xff0c;需要上传一个营业执照&…

【已验证】php配置连接sql server中文乱码(解决方法)更改utf-8格式

解决数据库中的中文数据在页面显示乱码的问题 在连接的$connectionInfo中设置"CharacterSet" > "UTF-8"&#xff0c;指定编码方式即可 $connectionInfo array("UID">$uid, "PWD">$pwd, "Database">$database…

黑马程序员微服务SpringCloud实用篇01

SpringCloud01 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.学习目标 了解微服务架构的优缺点 1.1.单体架构 单体架构&#xff…

ChatGPT 上新,效果炸裂,知识平台才是大模型的最佳狩猎场

数新网络_让每个人享受数据的价值浙江数新网络有限公司是一家开源开放、专注于云数据智能操作系统和数据价值流通的服务商。公司自主研发的DataCyber云数据智能操作系统&#xff0c;主要包括数据平台CyberData、人工智能平台CyberAI、数据智能引擎CyberEngine、数据安全平台Cyb…

希亦ACE和石头m1这两款内衣洗衣机哪一款更好?高性价比内衣洗衣机测评

内衣洗衣机可以说是近两年很火爆的小家电了&#xff0c;给大家带了一种全新的时尚体验&#xff0c;越来越内衣裤也可以用手洗&#xff01;而且还比手洗得干净&#xff01;不过现在市面上关于内衣洗衣机的品牌越来越多&#xff0c;小伙伴们想要挑选一款性价比高的内衣洗衣机看得…

python之SPC:计算Cpk

目录 1、Ca、Cp和Cpk的理解 2、python计算Cp,Cpk与Pp,Ppk 3、总结 1、Ca、Cp和Cpk的理解 Ca、Cp和Cpk是制程能力指数&#xff0c;它们分别代表制程准确度、制程精密度和制程能力指数。 制程准确度&#xff08;Ca&#xff09;反映实际平均值与规格中心值之一致性。对于单边…

C#中.NET 7.0不再支持ADO.NET,.NET Framwork依旧支持

目录 一、.NET 7.0框架下任何应用不再支持ADO.NET 二、.NET Framwork框架下Windows窗体应用支持ADO.NET 三、.NET 7.0不支持ADO.NET的真正原因 经过一阵折腾&#xff0c;终于可以确证C#中.NET框架不再支持用户通过ADO.NET的实体框架模型访问数据库&#xff0c;无论是.NET 7…

供应原厂电流继电器 - HBDLX-21/3 整定电流范围0.1-1.09A AC220V

HBDLX系列型号&#xff1a; HBDLX-20/1零序过电压继电器&#xff1b;HBDLX-20/2零序过电压继电器 HBDLX-20/3零序过电压继电器&#xff1b;HBDLX-20/4零序过电压继电器 HBDLX-20/5零序过电压继电器&#xff1b;HBDLX-21/1零序过电压继电器 HBDLX-21/2零序过电压继电器&#xf…

【Python】pact-python模块进行契约测试

Pact是一个契约测试框架&#xff0c;有多种语言实现&#xff0c;本文主要介绍模块pact-python进行契约测。 官网&#xff1a;https://docs.pact.io/implementation_guides/python/readme 安装命令&#xff1a;pip install pact-python 安装过程中如果报错&#xff0c;安装失…