深入理解I/O模型

news2024/11/28 4:58:46

目录

一、I/O 模型简介

二、I/O 模型

2.1 同步阻塞 I/O

        2.2 同步非阻塞I/O

        2.3 I/O多路复用

        2.4 异步I/O

        2.5 信号驱动 I/O

三、总结


一、I/O 模型简介

        所谓的 I/O 就是计算机内存与外部设备之间拷贝数据数据的过程。有 5 中 I/O 模型,分别是同步阻塞 I/O、同步非阻塞 I/O、多路复用I/O、信号驱动 I/O 和异步 I/O。为什么需要这么多的 I/O 模型呢?

        CPU 访问内存的速度远远高于外部设备,因此 CPU 是先把外部设备的数据读取到内存里,然后进行处理。当你的程序向外部设备发起一个读指令时,数据从外部设备拷贝到内存里需要一段时间才能完成,这个时候 CPU 做什么工作呢?是让 CPU 处理其他工作,还是让 CPU 不停地去查数据?这就是 I/O 模型要解决的问题,这里来探讨下各种网络模型。

二、I/O 模型

        对于一个网络 I/O 的通信过程,比如网络数据读取,会涉及两个对象,一个是调用这个操作的用户线程,一个是操作系统的内核。一个进程的地址空间分为用户空间和内核空间,用户线程不能直接访问内核空间。

        当用户发起一个网络数据读取的 I/O 操作后,会经历以下两步:

  • 用户线程等待内核将数据从网卡拷贝到内核空间
  • 内核将数据从内核空间拷贝到用户空间

        各种 I/O 模型的区别就是他们实现这两步的方式不一致。

2.1 同步阻塞 I/O

        同步阻塞 I/O (BIO) 是一种最基本的 I/O 模型,也是最常见的 IO 处理方式。在同步阻塞 I/O 模型中,当一个进程或线程发起一个 I/O 请求,该进程或线程会一直阻塞着,直到请求完成为止。

        比如读取网络数据,用户线程发起 reda 调用后就阻塞了,内核等待网卡数据到来,把数据从网卡拷贝到内核空间,再把用户线程唤醒。

        同步阻塞 I/O 模型相对实现比较简单,易于理解和编码,在低并发场景下,可以保证数据的及时处理和响应。但在高并发场景下效率低下,因大量线程可能被阻塞,导致CPU资源浪费,难以扩展到大量并发并发连接的情况,创建大量线程上下文切换开销大,容易出现性能瓶颈。

        2.2 同步非阻塞I/O

        同步非阻塞 I/O(Non-Blocking IO)是一种 IO 模型,用户线程不断的发起 read 调用,数据没到内核空间时,每次都返回失败直到数据到了内核空间,这一次 read 调用后,在等待数据从内核空间拷贝到用户空间这段时间里,现成还是阻塞的,等数据到了用户空间在把数据唤醒。

        在 BIO 中,调用者在等待I/O操作完成之前不能做任何事情,而在同步非阻塞 I/O 中,调用者可以继续执行其他任务而无需等待 I/O 操作完成。

        同步非阻塞 I/O 具有以下特点:

  • 尽管 I/O 操作是非阻塞的,但应用程序仍然负责检查 I/O 操作的状态,因此从某种意义上来说,这种模型仍然是同步的,因为需要应用程序主动查询结果。
  • 线程不会因为等待 I/O 操作而被阻塞,从而可以继续执行其它任务,提高了线程利用率。
  • 应用程序必须定期检查 I/O 操作是否可以继续进行,可以通过轮询实现。
  • 与 BIO 相比实现比较复杂,因为要求应用程序管理 I/O 操作的状态和重试逻辑。

        2.3 I/O多路复用

        I/O 多路复用(I/O Multiplexing)是一种高效地处理多个 I/O 流的方法,允许一个单一的线程管理多个文件描述符(如网络套接字、文件、管道等)的 I/O 操作。它克服了同步阻塞 I/O 和同步非阻塞 I/O 的局限性,特别是当需要处理大量并发连接时,能极大地提高系统的响应性和资源利用率。

        在 I/O 多路复用中,操作系统提供了一种机制,可以监视多个文件描述符并在其中一个或多个描述符准备就绪时通知应用程序。这样,应用程序就可以在一个循环中处理多个 I/O 流,而不需要为每个流维护一个独立的线程。

        用户线程的读取操作分为两步,线程先发起 select 调用,目的是问内核数据准备好了没有?等内核把数据准备好了,用户线程在发起 Read 调用。在等到数据从内核拷贝到用户空间这段时间内,线程还是阻塞的。多路复用的意思是,一次 select 调用可以向内核查多个数据通道(channel)的状态,所以叫多路复用。

        常见的 I/O 多路复用技术

  • select():这是最古老的多路复用函数,它允许一个进程监控多个文件描述符,等待一个或多个描述符变为可读、可写或发生异常。select() 有最大描述符数量的限制,并且数量随着描述符的增加而降低。
  • poll():类似于 select(),但是没有描述符数量的限制。poll() 使用链表存储描述符,因此在描述符数量过多时,效率比 select() 高
  • epoll():这时一个更高效率的多路复用函数,专门为高并发设计。epoll() 使用事件驱动的方式,可以注册、修改和删除感兴趣的事件,而且效率不随描述符的增加而显著降低。

        I/O 多路复用可以使用较少的线程甚至单线程来处理大量并发连接,减少了线程上下文切换的开销。能够迅速响应 I/O 事件,提高了整体响应速度。适用于高并发场景。

        I/O 多路复用的例子很多,比如 Redis 中使用多路复用来处理客户端的链接和请求、Tomcat中的 NioEndPoint 使用多路复用技术、Nginx 中也使用到了多路复用技术等等。

        2.4 异步I/O

        异步 I/O(Asynchronous I/O)允许应用程序发起 I/O 请求后立即返回控制流,而无需等待I/O 操作完成。异步 I/O 的设计目标是为了提高系统的响应性和效率,尤其是当 I/O 操作可能非常耗时(如磁盘读写、网络通信)时。

        异步 I/O 的特点如下:

  • 非阻塞:应用程序在发起 I/O 请求后不会立即被阻塞,可以立即返回并执行其它操作。
  • 事件驱动:I/O 操作完成通过事件通知给应用程序,应用程序通过事件循环或回调函数来响应这些事件。
  • 并行性:应用程序可以同时发起多个 I/O 请求,而无需等待前一个请求完成。
  • 效率高:通过避免阻塞,可以有效的利用计算资源,提高系统整体的响应能力。

        2.5 信号驱动 I/O

        信号驱动I/O(Signal-driven I/O)是一种特殊的I/O模型,主要用于Unix和类Unix系统中。在这种模型下,当一个I/O操作准备就绪时,内核会向应用程序发送一个信号,告知它可以进行I/O操作了。信号驱动I/O主要在处理网络I/O时使用,特别适用于套接字(socket)操作。

三、总结

        每种 I/O 模型的选择取决于应用程序的具体需求,包括预期的并发级别、性能要求、资源使用效率和开发复杂度。在实际应用中,开发人员可能会根据系统的需求和约束,混合使用上述模型以达到最佳效果。例如,一个高性能的 Web 服务器可能会使用 I/O 多路复用来处理网络连接,同时在内部数据处理中使用异步 I/O 来加速文件读写。

往期经典推荐:

深入浅出 Spring @Async 异步编程的艺术-CSDN博客

Sentinel与Nacos强强联合,构建微服务稳定性基石的重要实践_sentinel 整合nacos-CSDN博客

云原生基石:解码Docker镜像分层-CSDN博客

手把手教你实现服务高可用性_服务高可用方案-CSDN博客

Redis高性能的秘密原来在这,超越想象-CSDN博客

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

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

相关文章

单端、差分信号处理抗干扰能力解析

采用仪表运放对信号源进行处理, 信号源地上有共模干扰,经过差分信号处理后Vout上不会有干扰,差分信号可以非常好的抗共模干扰。 经过差分信号处理后,以单端信号输出进入ADC还是会有干扰,所以信号链采用差分 处理后&…

Java二十三种设计模式-适配器模式(6/23)

适配器模式:使不兼容的接口协同工作的桥梁 引言 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间可以一起工作,通过将一个类的接口转换成客户端期望的另一个接口。 在计算机编程中&#x…

AI论文精读笔记-MAE

1. 论文基本信息 论文标题:Masked Autoencoders Are Scalable Vision Learners 作者:Kaiming He∗,† Xinlei Chen∗ Saining Xie Yanghao Li Piotr Doll ́ ar Ross Girshick 发表时间和期刊:19 Dec 2021; arxiv 论文链接:Mas…

苹果预计因Apple Intelligence引发设备升级潮

🦉 AI新闻 🚀 苹果预计因Apple Intelligence引发设备升级潮 摘要:据彭博社报道,摩根士丹利将苹果列为首选股票,预期Apple Intelligence发布将引发创纪录的设备升级。分析师Erik Woodring 将苹果目标股价上调至273美元…

前端开发(基础)

目录 一、Web前端项目初始化 环境准备 创建项目 前端工程化配置 引入组件库 开发规范 全局通用布局 基础布局结构 全局底部栏 动态替换内容 全局顶部栏 通用路由菜单 支持多套布局 请求 请求工具库 全局自定义请求 自动生成请求代码 全局状态管理 全局权限管…

电力调度台如何助力电力指挥中心更智慧

在现代电力系统的复杂运行环境中,电力调度台正逐渐成为电力指挥中心实现智慧化管理的关键力量。 电力调度台具备强大的信息集成与处理能力。它能够将来自不同监测系统、传感器和数据源的海量数据汇聚一处,包括电力设备的实时运行状态、电力负荷的动态变化…

应急靶场(4):Windows Server 2019 - Web3

目录 一、攻击者的两个IP地址 二、隐藏用户名称 三、黑客遗留下的flag【3个】 下载好靶场(前来挑战!应急响应靶机训练-Web3)并搭建好环境,使用帐号密码(administrator / xj123456)登录靶机。 一、攻击者的两…

张幼玲:心中有火,眼里有光照医路

在我们的传统社会中,男科医生这一职业往往被人们带着异样的眼光看待。然而,张幼玲却选择了这一领域,成为了一名专业男科医生。他以其丰富的临床经验、高超的医术和对患者的关爱,赢得了患者和社会的广泛赞誉。 张幼玲出生于一个中医…

ASP.NET Core----基础学习06----将所有数据在页面中显示 布局页面的使用

文章目录 1. 将数据以list的形式展示在页面中2. 布局页面的使用3. 自定义设置视图文件是否需要加载的JS 1. 将数据以list的形式展示在页面中 step1:在接口文件中添加新的方法GetAllStudents() step2:在mock的数据中添加方法GetAllStudents(&a…

7/13 - 7/15

vo.setId(rs.getLong("id"))什么意思? vo.setId(rs.getLong("id")); 这行代码是在Java中使用ResultSet对象(通常用于从数据库中检索数据)获取一个名为"id"的列,并将其作为long类型设置为一个对象…

Billu_b0x靶机

信息收集 使用arp-scan 生成网络接口地址来查看ip 输入命令: arp-scan -l 可以查看到我们的目标ip为192.168.187.153 nmap扫描端口开放 输入命令: nmap -min-rate 10000 -p- 192.168.187.153 可以看到开放2个端口 nmap扫描端口信息 输入命令&…

工作中项目git如何管理,冲突,push不上去如何解决

主要涉及的知识点 现在公司中一般的git仓库的管理方式是怎么样的代码为什么push不上线上仓库如何解决代码冲突 分支管理方式 git checkout -b 分支名字 是创建并切换到分支 git push origin 分支名字 推到远程仓库分支上 主流的git管理方式 共用一个仓库,不同…

Golang | Leetcode Golang题解之第237题删除链表中的节点

题目: 题解: func deleteNode(node *ListNode) {node.Val node.Next.Valnode.Next node.Next.Next }

解决宝塔Spring Boot项目获取不到环境变量的问题

问题描述 在使用宝塔面板管理Spring Boot项目时,可能会遇到代码无法获取 /etc/profile 文件中设置的Linux环境变量的问题。虽然在SSH终端中可以正常获取,但在通过宝塔面板启动的Spring Boot项目中,环境变量却无法被读取。 解决方案&#xf…

TS 入门(三):Typescript函数与对象类型

目录 前言回顾1. 函数类型a. 基本函数类型b. 可选参数和默认参数c. 剩余参数 2. 对象类型a. 基本对象类型b. 可选属性和只读属性 3. 类型别名和接口a. 类型别名b. 接口扩展 4. 类型推断和上下文类型a. 类型推断b. 上下文类型 扩展知识点:函数重载结语 前言 在前两章…

实验06 持续集成测试

知识点 集成测试定义 集成测试是将多个单元组合起来形成更大的单元,并测试它们是否能协同工作形成子系统。一种旨在暴露单元接口之间、组件/系统间交互或协同工作时所存在的缺陷的测试。 集成测试关注的问题 模块间数据传递是否正确。一个模块的功能是否影响另一…

[iOS]内存分区

[iOS]内存分区 文章目录 [iOS]内存分区五大分区栈区堆区全局区常量区代码区验证内存使用注意事项总结 函数栈堆栈溢出栈的作用 参考博客 在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域 还记得OC是C的超类 所以C的内存分区也是一样的 iOS系统中&a…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑频率不同响应阶段的惯量评估优化策略》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

嵌入式人工智能(6-树莓派4B按键输入控制LED)

1、按键 按键的原理都是一样,通过按键开关的按下导通,抬起断开的情况,GPIO引脚来检测其是否有电流流入。GPIO有input()方法,对于GPIO引脚检测电流,不能让其引脚悬空,否则引脚会受周边环境电磁干扰产生微弱…

《昇思25天学习打卡营第15天|计算机视觉-SSD目标检测》

FCN图像语义分割&ResNet50迁移学习&ResNet50图像分类&ShuffleNet图像分类&SSD目标检测 SSD目标检测 模型简介 SSD,全称Single Shot MultiBox Detector,是Wei Liu在ECCV 2016上提出的一种目标检测算法。使用Nvidia Titan X在VOC 2007测…