【linux高级IO(一)】理解五种IO模型

news/2024/7/8 9:50:39 标签: linux, 运维, 服务器, IO

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:Linux从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学更多操作系统知识
  🔝🔝


在这里插入图片描述

Linux高级IO

  • 1. 前言
  • 2. 重谈对IO的理解
  • 3. 阻塞IO讲解
  • 4. 非阻塞IO讲解
  • 5. 信号驱动IO
  • 6. IO多路转接
  • 7. 异步IO
  • 8. 理解异步和同步
  • 9. 总结以及拓展

1. 前言

本篇文章开始, 将与大家分享高级IO相关的内容
本章重点:

本篇文章会带大家初识五种常见的IO模型, 分别是: 阻塞IO, 非阻塞IO, 信号驱动IO, IO多路转接, 异步IO. 其中, 多路转接将会是本系列文章后续的重点


IO_22">2. 重谈对IO的理解

IO: input or output --> 访问外设 效率低
IO一定是非常低效的, 以读取为例:

当我们read/recv时, 如果底层缓冲区没有数据, read/recv函数会阻塞
当我们read/recv时, 如果底层缓冲区有数据, read/recv函数会拷贝

所以说, IO = 等待 + 拷贝 !!!

记住这句话, 会一直贯穿整个IO系列文章

探讨低效IO和高效IO:

很明显, IO = 等待 + 拷贝.
所以可以得出下面的结论:

  • 低效IO: 单位时间内, 大部分时间, IO类接口都在等待
  • 高效IO: 让等待的比重降低

接下来的五种IO模型, 就是围绕着是否高效进行的


IO_45">3. 阻塞IO讲解

正如其名, 阻塞IO 在内核将数据准备好之前, 系统调用会一直等待, 并且所有的套接字默认都是阻塞IO. 阻塞IO是最常见的IO模型, 它比较好理解, 下面是关于阻塞IO的图像讲解

在这里插入图片描述

通俗来讲, 阻塞IO就是, 你去河边钓鱼, 只拿一根鱼竿等于上钩, 并且时刻盯着水面


IO_53">4. 非阻塞IO讲解

顾名思义, 非阻塞IO就是说, 当底层数据没有准备就绪时, 不会傻傻的等待, 而是直接返回. 但是调用recv时, 出现错误也会直接返回, 应该怎样区分这两种情况呢? 答案是阻塞式IO的正常返回时, 会将errno全局遍历设置为宏: EWOULDBLOCK. 这下就能将它们区分开了

在这里插入图片描述

非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符, 这个过程称为轮询. 这对CPU来说是较大的浪费, 一般只有特定场景下才使用. 下面是非阻塞IO的简单示例:

#include <fcntl.h>
#include <unistd.h>
#include<errno.h>
#include <cstdlib>
#include <iostream>
using namespace std;

//对指定的fd设置非阻塞
void SetNonBlock(int fd) {
    int fl = fcntl(fd, F_GETFL);
    if (fl < 0) {
        cerr << "fcntl error" << endl;
        exit(1);
    }
    fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}

int main() {
    SetNonBlock(0);
    while (1) {
        char buffer[1024];
        ssize_t s = read(0, buffer, sizeof(buffer) - 1);
        if (s > 0) {
            buffer[s] = 0;
            cout << buffer << endl;
        } else if (s == 0) {
            cout << "读到文件结尾了" << endl;
            break;
        }
        else
        {
            //1. 数据没用准备好 2. 真的出错了. 都以-1的返回值返回
            // 数据没有准备好,不算出错. 需要区分这两种情况
            if(errno == EWOULDBLOCK || errno == EAGAIN)
            {
                cout<<"os底层数据还没就绪"<<endl;
                cout<<errno<<endl;
            }
            //被信号中断, 也不算read出错
            else if(errno == EINTR)
            {
                cout<<"IO interrupted by signal"<<endl;
            }
            else
            {
                cout<<"read error"<<endl;
                break;
            }
        }
        sleep(1);
    }
}

调用fcntl函数将fd设置为非阻塞

通俗来讲, 非阻塞IO就是, 你去河边钓鱼, 也只用一根鱼竿, 但是你过一分钟才去看看有没有鱼上钩, 其他时间你可能在刷抖音


IO_122">5. 信号驱动IO

信号驱动IO: 内核将数据准备好的时候, 使用SIGIO信号通知应用程序进行IO操作. 也就是说信号驱动的方式你不用像非阻塞IO一样, 每过一段时间去检查是否有数据就绪, 一旦有数据就绪, 会有信号通知你, 这也就可以更多时间刷抖音了(不是)

在这里插入图片描述

通俗来讲, 信号驱动IO就是, 你去河边钓鱼, 也只拿一个鱼竿, 只不过鱼竿上有压力传感器, 一旦有鱼上钩就会发出声音提醒你. 其余时间我们当然可以愉快的刷抖音


IO_131">6. IO多路转接

前面几个钓鱼的人是不是有点寒酸了?一次只拿一个鱼竿, 效率太低了吧! 多路转接直接把桌子掀了, 它拿了100个鱼竿去钓鱼: IO多路转接能够同时等待多个文件描述符的就绪状态

在这里插入图片描述

通俗来说就是你拿一百个鱼竿去钓鱼, 同时等待一百种可能, 一旦有鱼上钩了, 会同时把所有上钩的鱼都拉上来, 这效率简直是指数级增长, 所以这也是在实际生活中使用的最多的IO方案


IO_140">7. 异步IO

前面所有的IO方式, 都是同步IO, IO=等待+拷贝, 同步IO就是要么参与了等待过程, 要么参与了拷贝过程, 要么都参与了. 而异步IO则是等待和拷贝都不参与: 由内核在数据拷贝完成时, 通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据).

在这里插入图片描述

还是拿钓鱼的例子来说, 前面的钓鱼者, 不管你一次性带多少鱼竿(多路转接), 不管你在鱼竿上安装什么高科技(信号驱动), 但是你总得去河边, 自己拿着鱼竿钓鱼. 而异步IO是怎么做的呢? 他直接雇佣了一个人帮它去钓鱼, 什么时候鱼上钩, 你等待了多久我都不在乎, 我只需要你在晚上九点的时候将钓的鱼全部带给我即可.


8. 理解异步和同步

同步和异步关注的是消息通信机制.

在这里插入图片描述

同步和异步在实际场景中怎样运用?

虽然说大部分IO类型都是同步IO, 但是实际生活中运用异步IO的概率也不小. 举个例子, 你是王者荣耀的后端, 一个英雄放了一个技能打在对面身上, 此时我们后端要将这个操作做成同步的还是异步的? 很明显是同步, 因为我想要实时的看见对面英雄的血条在减少. 再举个例子, 现在你是QQ的后端, 你现在要查询一千万个QQ号中, 有哪些QQ号超过1个月没有上线了. 你把此功能做成同步还是异步? 很明显考虑到成本问题一定是做成异步, 一千万个QQ号如果用一台机器可能会查询几个小时, 你可能会说, 那我可以用多台机器做负载均衡, 是的没错, 但是机器数量多了, 成本就上去了. 所以做成异步的IO比较好

综上所述, 实际场景中要根据自己的情况和需求来觉得使用同步还是异步, 不要觉得在学习时都用同步, 以后工作了也就无脑的用同步


9. 总结以及拓展

本篇文章只是简单的介绍了IO模型的几个分类, 其中, 最重要的模型是多路转接, 后面的文章会着重讲解它. 多路转接为什么重要? 因为它是业内最常用的用来提高并发性的模型, 后续大家都接触都reactor模型, 而reactor模型可以有多种实现方式, 而效率最高的reactor模型则是用多路转接实现的!!!


🔎 下期预告:多路转接之select 🔍

http://www.niftyadmin.cn/n/5537025.html

相关文章

配置基于不同IP地址的虚拟主机

定义配置文件vhost.conf <directory /www> allowoverride none require all granted </directory> <virtualhost 192.168.209.136:80> documentroot /www servername 192.168.209.136 </virtualhost><virtualhost 192.168.209.138:80> document…

安装KB5039212更新卡在25% 或者 96% 进度

系统之家7月1日消息&#xff0c;微软在6月11日的补丁星期二活动中&#xff0c;为Windows 11系统推出了KB5039212更新。然而&#xff0c;部分用户在Windows社区中反映&#xff0c;安装过程中出现失败&#xff0c;进度条在25%或96%时卡住。对于遇到此类问题的Windows 11用户&…

普罗索福特 ProSoft MVI56-PDPMV1控制器 处理器 模块

MVI56-PDPMV1 是一款功能丰富的工业自动化通信模块&#xff0c;特征和作用如下&#xff1a; 参数与规格&#xff1a; 功能&#xff1a;作为PROFIBUS网络扫描仪&#xff0c;在PROFIBUS设备和处理器数据之间传输输入和输出数据。 通信协议&#xff1a;支持PROFIBUS MVI56-PDPMV…

华为HCIP Datacom H12-821 卷28

1.单选题 下面是一台路由器的部分配置,关于该部分配置描述正确的是,[HUAWEI]ip ip-prefx pl permit 10.0.192.0 8greater-equal17 less-equal 18 A、10.0.192.0/8网段内,掩码长度为18的路由会匹配到该前缀列表,匹配规则为允许 B、10.0.192.0/8网段内掩码长度为21的路…

实体零售连锁企业如何通过物流接口实现数智化转型升级?

在电子商务浪潮的持续冲击下&#xff0c;传统的实体零售行业面临着巨大的挑战。为了在线上线下融合的新零售时代保持竞争力&#xff0c;众多实体零售企业积极寻求数字化转型的突破。 某中国零售连锁百强企业近年来致力于打造自有品牌的线上销售体系&#xff0c;自2021年8月起接…

【SQL】已解决:SQL错误(15048): 数据兼容级别有效值为100、110或120

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决SQL错误(15048): 数据兼容级别有效值为100、110或120 在数据库开发和管理过程中&#xff0c;我们经常会遇到各种各样的错误。本文将详细分析SQL错误(15048)的背景、可能原因、…

01.音视频小白系统入门(新专栏)

目录 一、基础知识 二、音频 三、视频 四、流媒体服务器 五、收获 音视频技术在远程办公、在线教育、远程医疗等领域的应用广泛。 学习音视频技术有助于提升职业竞争力&#xff0c;满足市场需求。 掌握音视频基础知识对未来发展至关重要&#xff0c;基础不牢会导致后续学习…

每天五分钟计算机视觉:人体姿势识别

本文重点 人体姿势识别是计算机视觉领域的一个重要研究方向,旨在通过图像或视频数据自动检测并识别出人体的各种姿势和动作。随着深度学习技术的快速发展,基于神经网络的方法在这一领域取得了显著进展。神经网络,特别是卷积神经网络(CNN)和循环神经网络(RNN),因其强大…