当前位置: 首页 > 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;这并…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...