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

谈谈各种IO模型

目前的IO模型有5种BIO(阻塞IO)、NIO(非阻塞IO)、IO多路复用、信号驱动IO、异步IO(AIO)

了解这些模型之前,我们需要先知道IO模型中的几个概念:阻塞&非阻塞、同步&异步

阻塞是一个线程的状态,也就是操作系统会将线程或者进程挂起,让线程处于阻塞状态,这时候线程就是一直等待的状态,然后必须由操作系统或者其他线程唤醒才能进入就绪态进而到运行态。

非阻塞那就是相反了,会立即返回,不会一直等待。

所以我们看是否阻塞其实就看是否会立即返回,有没有一直等待

看是异步还是同步,就是看最终读取的结果是不是全程由操作系统完成,如果需要应用程序参与的那就是同步。

那我们就拿网络通信,一个应用程序A向一个应用程序B进行消息传递。

我们都知道网络通信是TCP协议,那么这时候内存是有TCP的发送缓冲区和接收缓冲区的。

那么当应用程序A向应用程序B发送消息的时候,当消息到达应用程序B的接收缓冲区的时候,应用程序B就会发起recfrom系统调用,操作系统就会将数据从内存拷贝到应用程序B,那我们知道消息肯定是不间断的,应用程序B也不知道什么时候应用程序A会向其发送消息。

那么这里就是本文讲解IO模型的入口点。对啊?应用程序B怎么知道什么时候应用程序A会向其发送消息,所以

阻塞IO(BIO)就是:

当应用程序发起recfrom函数的时候,如果此时没有得到结果,那么操作系统就会想应用程序B的线程挂起,让其处于阻塞的状态,等有结果了,操作系统就会将应用程序B线程唤醒让其从就绪态进入运行态,然后再把结果返回给应用程序B。

具体流程是这样的。

非阻塞IO(NIO)就是                                                      

当没有得到结果返回时,也不会将应用程序挂起,而是操作系统会返回一个错误标识立即返回,不会让应用程序B一直等待,让其可以做其他事情。但是应用程序B需要自己不断的调用recvfrom询问操作系统是否有结果返回。

那么应用程序B一直询问操作系统有没有数据,一直需要调用recvfrom,那么如果在并发的情况下,有很多个请求同时向应用程序B发送消息,那么这时候应用程序就得开启N个线程,每个线程都得去recvfrom函数调用,线程是宝贵的资源,单独就干询问这一事,大大浪费了资源没有好好利用。所以能不能有一个结构可以作为监控,让应用程序B不用一直去询问操作系统,当有数据返回的时候,这个监控器就可以监控到,然后安排线程去读取呢?那么就是后面演化的IO多路复用

IO多路复用就是

复用,指的就是线程复用,一个线程可以处理多个IO请求,应用程序通过select/poll/epoll等系统调用,等某一个请求有数据就绪的时候,就可以分配线程去调用recvfrom函数去获取返回结果。select操作可能会阻塞,直到有某个请求数据就绪的时候才不会阻塞,但是阻不阻塞其实取决于timeout参数,值为0,那么就是没有请求数据就绪就直接返回,不用阻塞等待,可以干其他事情,

解决了一个线程可以处理多个并发IO请求的问题。

那么频繁的轮询是会增加cpu的负担的,因为有些轮询其实是空轮询。那么有没有什么办法可以不用轮询呢?那么就是接下要介绍的信号驱动型IO

信号驱动型IO就是

应用程序会调用sigaction函数为一个或多个IO请求设置信号处理函数,此操作是直接返回的,不会阻塞,可以继续干其他事情,当有请求IO数据准备就绪的时候,操作系统就会发送一个SIGIO信号,那么之前设置过信号处理函数就会被触发,应用程序就会收到通知,此时应用程序就会在信号处理函数里面通过recvfrom函数调用获取结操作系统结果。

这就是信号驱动型IO,我们发现信号驱动型IO是非阻塞的。

上面4种都是同步型IO,也就是说都需要由应用程序参与等待操作系统将数据从内核拷贝到应用程序的过程。

最后一种是异步IO,什么是异步IO,

异步IO就是应用程序发起一个read或者write请求的时候,后面的事就完全不用参与了,此时如果数据还没准备就绪就会立即返回,不用阻塞等待,可以继续干其他事,如果数据准备就绪,那么操作系统会将数据从内存拷贝到应用程序,然后通过回调通知应用程序,应用程序就可以直接读取就行了,不用再由应用程序去自己参与拷贝了。也就是完成是一种“发出指令,坐享其成”。

总结:

IO模型就是5种,同步阻塞IO,同步非阻塞IO,IO多路复用,信号驱动型IO,异步IO

如何判断是同步还是异步:

是否需要由应用程序参与全部的过程。需要参与就是同步,不需要参与就是异步。

如何判断是阻塞还是非阻塞:

是否会立即返回,是否会一直等待。会一直等待就是阻塞,不会一直等待就是非阻塞。

http://www.xdnf.cn/news/435385.html

相关文章:

  • 算法·KMP
  • 1688 API 接口使用限制
  • 【C++】多线程和多进程
  • Java Spring 事件驱动机制
  • 中医诊所药房开处方调剂库存管理h5/pc开源版开发
  • 提供全球86国/地区进出口税费,46国/地区监管条件,53国/地区税费计算
  • 第二十三天打卡
  • 项目管理系统流程:高效运作的关键所在
  • 使用ADB命令操作Android的apk/aab包
  • [SAP] 通过程序名获取事务码TCode
  • Python实例题:Pvthon实现简单的Web服务器
  • AI 编程新时代!字节 Seed-Coder 重磅登场
  • 第六章QT基础: Lambda表达式补充
  • [250513] “End of 10” 活动:应对 Windows 10 支持终止,推广 Linux 转型
  • livenessProbe 和 readinessProbe 最佳实践
  • Pytorch学习笔记(二十二)Audio - Audio I/O
  • 论文《Collaboration-Aware Graph Convolutional Network for Recommender Systems》阅读
  • 打卡DAY24
  • 【调度算法】LaCAM快速多智能体路径搜索算法
  • LLM大模型transform架构的核心知识
  • 《从协议层面剖析 VoIP 通信:SIP 信令流中的 RPort、注册与呼叫建立机制》
  • 20250512期:基于arcpy数据驱动的大批量规范化出图
  • 油桃缺陷检测数据集VOC+YOLO格式559张2类别
  • AI助力:零基础开启编程之旅
  • 【JavaScript】原生 JavaScript 实现 localStorage 过期时间
  • Linux常用命令39——free显示系统内存使用量情况
  • 软件测试——面试八股文(入门篇)
  • 项目三 - 任务6:回文日期判断
  • 飞拍技术介绍
  • 从数据中台到数据飞轮:数字化转型的演进之路