当前位置: 首页 > news >正文

五种I/O模型

目录

  • 1、阻塞IO模型
  • 2、非阻塞IO模型
  • 3、IO多路复用模型
  • 4、信号驱动IO模型
  • 5、异步IO模型
  • 总结

  1. blockingIO - 阻塞IO
  2. nonblockingIO - 非阻塞IO
  3. IOmultiplexing - IO多路复用
  4. signaldrivenIO - 信号驱动IO
  5. asynchronousIO - 异步IO

5种模型的前4种模型为同步IO,只有异步IO模型是异步IO操作

首先,我们知道对于一个网络输入操作通常包括两个不同阶段:

第一阶段:等待网络数据到达网卡→读取到内核缓冲区(数据准备好)

第二阶段:从内核缓冲区复制数据到进程缓冲区(复制数据了)

这很显然是两个操作,所以我们重点关注以下2点操作:

A、等待数据读取到内核缓冲区(数据准备)

B、复制内核缓冲区数据到进程缓冲区(数据复制)

1、阻塞IO模型

进程发起IO系统调用后,进程被阻塞,转到内核空间处理,整个IO处理完毕后返回进程。

调用者调用了某个函数,等待这个函数返回,期间什么也不做,不停的去检查这个函数有没有返回,必须等这个函数返回才能进行下一步动作。

即:A阻塞,B阻塞

举例:

你准备去书店买书,但老板不在,留了电话

你打电话问老板:有没有《三体》卖?

老板查了一下说:书店里没有《三体》,我打个电话让供应商送货,你等一下

然后你就一直在书店里等着,不吃饭,不睡觉(进入A阶段,等待数据,陷入了IO阻塞)

过了一段时间,供应商把书送到书店

老板打电话给你:书已经到了,你有空吗?等你有空,我才当面把书交给你(进入B阶段,数据复制,阻塞住了)

交易完成

2、非阻塞IO模型

进程发起IO系统调用后,如果内核缓冲区没有数据,需要到IO设备中读取,进程返回一个错误而不会被阻塞,但会一直轮询内核缓冲区数据准备好了没。进程发起IO系统调用后,如果内核缓冲区有数据,内核就会把数据返回进程。

非阻塞等待,每隔一段时间就去检测IO事件是否就绪。没有就绪就可以做其他事。非阻塞I/O执行系统调用总是立即返回,不管时间是否已经发生,若时间没有发生,则返回-1,此时可以根据errno区分这两种情况,对于accept,recv和send,事件未发生时,errno通常被设置成eagain。

即:A不阻塞,B阻塞

举例:

你准备去书店买书,但老板不在,留了电话

你打电话问老板:有没有《三体》卖?

老板查了一下说:书店里没有《三体》,我打个电话让供应商送货,你先回家去吧,过几天再来问(进入A阶段,等待数据,但非阻塞)

想象:你回到家,该吃就吃,该喝就喝,隔了1周后才打电话问老板书到了没?(非阻塞,继续做别的事情)

但一般编程,都会设置轮询IO,即:

实际:你回到家,循环不停地打电话给老板,我的书到了没?(陷入事实上的轮询IO阻塞,相当于死循环,即使属于非阻塞模型)

过了1个小时,老板说:书已经到了,你有空吗?等你有空,我才当面把书交给你(进入B阶段,数据复制,阻塞住了)

交易完成

3、IO多路复用模型

多个进程的IO可以注册到一个复用器(select)上,然后用一个进程调用该复用器(select)。 复用器(select)会监听所有注册进来的IO。如果复用器(select)所监听的IO在内核缓冲区都没有可读数据,复用器(select)调用进程会被阻塞;而当任一IO在内核缓冲区中有可数据时,复用器(select)调用就会返回。之后复用器(select)通知注册进程来再次发起读取IO,读取内核中准备好的数据。

linux用select/poll函数实现IO复用模型,这两个函数也会使进程阻塞,但是和阻塞IO所不同的是这两个函数可以同时阻塞多个IO操作。而且可以同时对多个读操作、写操作的IO函数进行检测。知道有数据可读或可写时,才真正调用IO操作函数。

即:A不阻塞,B阻塞

举例:

对于书店老板来说,他对接的是多个客人。你,张三,李四都打电话给老板,要买书

你买《三体》,张三买《鲁迅》,李四买《史记》,然后最坏的情况,3本书老板都没有

老板说:我打个电话让供应商送货,你们先别一直打电话,书到了我再打电话让你们过来取

实际:你,张三,李四挂了电话,就去吃饭睡觉,做自己的事了(进入A阶段,等待数据,但非阻塞)

老板一直等不到供应商来送货,但自己需要一直等待着(陷入事实上的select/poll/epoll阻塞)

此时供应商送来一本书,但老板不知道属于谁,得遍历一边购书单,发现是你的书

老板打电话给你:书已经到了,你有空吗?等你有空,我才当面把书交给你(进入B阶段,数据复制,阻塞住了)

交易完成

4、信号驱动IO模型

当进程发起一个IO操作,会向内核注册一个信号处理函数 ,然后进程返回;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用IO读取数据

linux用套接口进行信号驱动IO,安装一个信号处理函数,进程继续运行并不阻塞,当IO时间就绪,进程收到SIGIO信号。然后处理IO事件。

即:A不阻塞,B阻塞

举例:

你准备去书店买书,但老板不在,留了电话

你打电话问老板:有没有《三体》卖?

老板查了一下说:书店里没有《三体》

然后你说:我给你留个收货地址。如果书到了,你打电话给我,我会让别人在这个地址接收你的书

然后你就回家去了,该干嘛干嘛(进入A阶段,等待数据,但留了回调函数,非阻塞)

老板打电话给你:书已经到了,让你的人准备好,我才当面把书交给你的人(进入B阶段,数据复制,阻塞住了)

交易完成

5、异步IO模型

当进程发起一个IO操作,进程立即返回,但也不返回结果;内核把整个IO处理完后,会通知进程结果。如果IO操作成功则进程直接获取到数据。所谓的通知进程结果,是指:包含将数据从内核复制到应该进程的缓冲区,完成后通知应用进程,也就是说,已经完成了A B 2个步骤了,才通知请求进程,此时请求进程直接获取到数据,根本不会阻塞,即所谓的异步。

linux中,可以调用aio_read函数告诉内核描述字缓冲区指针和缓冲区的大小、文件偏移及通知的方式,然后立即返回,当内核将数据拷贝到缓冲区后,再通知应用程序。

即:A不阻塞,B不阻塞

你准备去书店买书,但老板不在,留了电话

你打电话问老板:有没有《三体》卖?

老板查了一下说:书店里没有《三体》,你留个地址,书到了我会把书送到你家去

然后你就回家去了,该干嘛干嘛(进入A阶段,等待数据,非阻塞)

老板接收到供应商的书,把书放到你家楼下,而此时你在家睡觉(进入B阶段,数据复制,非阻塞)

老板打电话给你:书已经到了,在你家楼下,自己去拿吧

交易完成

总结

根据上面所说的IO操作的两个阶段,可以把上面的I/O模型进行如下归类:

阻塞IO:在两个阶段上面都是阻塞的,A阶段阻塞,B阶段还是阻塞
非阻塞IO:在A不阻塞(但陷入事实上的轮询IO阻塞),B阶段还是阻塞的
IO复用:A阶段不阻塞(陷入事实上的select/poll/epoll阻塞),B阶段还是阻塞的
信号IO:A阶段不阻塞,当信号通知程序数据准备完毕,B阶段还是阻塞的
异步IO:A阶段不阻塞,B阶段不阻塞

现在,我们可以看到,前4种IO模型的B阶段:数据复制阶段都是阻塞,也就是按POSIX标准来说的同步IO,最后1种异步IO模型,才是按POSIX标准来说的异步IO。

同步一般指主动请求并等待I/O操作完毕的方式,I/O操作未完成前,会导致应用进程挂起

而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知(异步的特点就是通知),这可以使进程在数据读写时也不阻塞

阻塞或者非阻塞I/O主要是指I/O操作第一阶段的完成方式(进程访问的数据如果尚未就绪),即数据还未准备好的时候,应用进程的表现

如果这里进程挂起,则为阻塞I/O,否则为非阻塞I/O,主要是描述进程在数据未准备好时的状态,根据进程等待数据时的状态来判断

阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式:

说白了就是一种读取或者写入操作函数的实现方式,阻塞方式下读取或者写入函数将一直等待

而非阻塞方式下,读取或者写入函数会立即返回一个状态值

相关文章:

五种I/O模型

目录 1、阻塞IO模型2、非阻塞IO模型3、IO多路复用模型4、信号驱动IO模型5、异步IO模型总结 blockingIO - 阻塞IOnonblockingIO - 非阻塞IOIOmultiplexing - IO多路复用signaldrivenIO - 信号驱动IOasynchronousIO - 异步IO 5种模型的前4种模型为同步IO,只有异步IO模…...

用nativescript开发ios程序常用命令?

NativeScript是一个用于跨平台移动应用程序开发的开源框架,允许您使用JavaScript或TypeScript构建原生iOS和Android应用程序。以下是一些常用的NativeScript命令,用于开发iOS应用程序: 1、创建新NativeScript项目: tns create m…...

6.Tensors For Beginners-What are Convector

Covectors (协向量) What‘s a covector Covectors are “basically” Row Vectors 在一定程度上,可认为 协向量 基本上就像 行向量。 但不能简单地认为 这就是列向量进行转置! 行向量 和 列向量 是根本不同类型的对象。 …...

Linux多线程网络通信

思路:主线程(只有一个)建立连接,就创建子线程。子线程开始通信。 共享资源:全局数据区,堆区,内核区描述符。 线程同步不同步需要取决于线程对共享资源区的数据的操作,如果是只读就不…...

矩阵的c++实现(2)

上一次我们了解了矩阵的运算和如何使用矩阵解决斐波那契数列&#xff0c;这一次我们多看看例题&#xff0c;了解什么情况下用矩阵比较合适。 先看例题 1.洛谷P1939 【模板】矩阵加速&#xff08;数列&#xff09; 模板题应该很简单。 补&#xff1a;1<n<10^9 10^9肯定…...

RPC 框架之Thrift入门(一)

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…...

【C++】运算符重载 ⑥ ( 一元运算符重载 | 后置运算符重载 | 前置运算符重载 与 后置运算符重载 的区别 | 后置运算符重载添加 int 占位参数 )

文章目录 一、后置运算符重载1、前置运算符重载 与 后置运算符重载 的区别2、后置运算符重载添加 int 占位参数 上 2 2 2 篇博客 【C】运算符重载 ④ ( 一元运算符重载 | 使用 全局函数 实现 前置 自增运算符重载 | 使用 全局函数 实现 前置 - - 自减运算符重载 )【C】运算符…...

538. 把二叉搜索树转换为累加树

题目描述 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下&#xff0c;二叉搜索树满足下列约束…...

java8日期时间工具类

【README】 1&#xff09;本文总结了java8中日期时间常用工具方法&#xff1b;包括&#xff1a; 日期时间对象格式化为字符串&#xff1b;日期时间字符串解析为日期时间对象&#xff1b;日期时间对象转换&#xff1b; 转换过程中&#xff0c;需要注意的是&#xff1a; Instan…...

算法-动态规划/trie树-单词拆分

算法-动态规划/trie树-单词拆分 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/word-break/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 动态规划 2.1 解题思路 dp[i]表示[0, i)字符串可否构建那么dp[i]可构建的条件是&…...

React框架核心原理

一、整体架构 三大核心库与对应的组件 history -> react-router -> react-router-dom react-router 可视为react-router-dom 的核心&#xff0c;里面封装了<Router>&#xff0c;<Route>&#xff0c;<Switch>等核心组件,实现了从路由的改变到组件的更新…...

python-pytorch 利用pytorch对堆叠自编码器进行训练和验证

利用pytorch对堆叠自编码器进行训练和验证 一、数据生成二、定义自编码器模型三、训练函数四、训练堆叠自编码器五、将已训练的自编码器级联六、微调整个堆叠自编码器 一、数据生成 随机生成一些数据来模拟训练和验证数据集&#xff1a; import torch# 随机生成数据 n_sample…...

制作 3 档可调灯程序编写

PWM 0~255 可以将数据映射到0 75 150 225 尽可能均匀电压间隔...

源码分享-M3U8数据流ts的AES-128解密并合并---GoLang实现

之前使用C语言实现了一次&#xff0c;见M3U8数据流ts的AES-128解密并合并。 学习了Go语言后&#xff0c;又用Go重新实现了一遍。源码如下&#xff0c;无第三方库依赖。 package mainimport ("crypto/aes""crypto/cipher""encoding/binary"&quo…...

CSDN Q: “这段代码算是在STC89C52RC51单片机上完成PWM呼吸灯了吗?“

这是 CSDN上的一个问题 这段代码算是在STC89C52RC51单片机上完成PWM呼吸灯了吗&#xff0c;还是说得用上定时器和中断函数#include <regx52.h> 我个人认为: 效果上来说, 是的! 码以 以Time / 100-Time 调 Duty, 而 for i loop成 Period, 加上延时, 实现了 PWM周期, 虽然…...

Linux系统编程系列之线程池

Linux系统编程系列&#xff08;16篇管饱&#xff0c;吃货都投降了&#xff01;&#xff09; 1、Linux系统编程系列之进程基础 2、Linux系统编程系列之进程间通信(IPC)-信号 3、Linux系统编程系列之进程间通信(IPC)-管道 4、Linux系统编程系列之进程间通信-IPC对象 5、Linux系统…...

Linux CentOS7 vim多文件与多窗口操作

窗口是可视化的分割区域。Windows中窗口的概念与linux中基本相同。连接xshell就是在Windows中新建一个窗口。而vim打开一个文件默认创建一个窗口。同时&#xff0c;Vim打开一个文件也就会建立一个缓冲区&#xff0c;打开多个文件就会创建多个缓冲区。 本文讨论vim中打开多个文…...

SPI 通信协议

1. SPI通信 1. 什么是SPI通信协议 2. SPI的通信过程 在一开始会先把发送缓冲器的数据&#xff08;8位&#xff09;。一次性放到移位寄存器里。 移位寄存器会一位一位发送出去。但是要先放到锁存器里。然后从机来读取。从机的过程也一样。当移位寄存器的数据全部发送完。其实…...

【图像处理】使用各向异性滤波器和分割图像处理从MRI图像检测脑肿瘤(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

5个适合初学者的初级网络安全工作,网络安全就业必看

前言 网络安全涉及保护计算机系统、网络和数据免受未经授权的访问、破坏和盗窃 - 防止数字活动和数据访问的中断 - 同时也保护用户的资产和隐私。鉴于公共事业、医疗保健、金融以及联邦政府等行业的网络犯罪攻击不断升级&#xff0c;对网络专业人员的需求很高&#xff0c;这并…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...