首页 > 其他分享 >阻塞IO、非阻塞IO、IO复用

阻塞IO、非阻塞IO、IO复用

时间:2023-06-02 11:45:28浏览次数:27  
标签:IO 模型 阻塞 复用 内核 奶茶 select

前言

在《Unix网络编程》一书中提到了五种IO模型,分别是:阻塞IO、非阻塞IO、IO复用、信号驱动IO以及异步IO。本篇文章主要介绍IO的基本概念以及阻塞IO、非阻塞IO、IO复用三种模型,供大家参考学习。

一、什么是IO

计算机视角理解IO:

对于计算机而言,任何涉及到计算机核心(CPU和内存)与其他设备间的数据转移的过程就是IO。IO对于计算机而言有两层意思:

  • IO 设备:比如我们最常见的打印机、鼠标、键盘。
  • 对IO设备的数据读写。

程序视角理解IO:

现代操作系统将空间划分为用户空间和内核空间。

  • 用户空间:非内核应用程序则运行在用户空间。用户空间中的代码运行在较低的特权级别上,不能直接访问内核空间和硬件设备。
  • 内核空间:操作系统的核心,是操作系统工作的基础,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。

 

操作系统为了能够正常平稳地运行下去,它是不会允许应用程序随意访问计算机硬件部分,如内存、硬盘、网卡,应用程序必须通过操作系统提供的API来访问,以达到安全的访问控制。

总结:IO对于应用程序而言,强调的是通过向内核发起系统调用完成对I/O的间接访问。

应用程序发起一次IO访问分为两个阶段:

  1. IO调用阶段:应用程序向内核发起系统调用。
  2. IO执行阶段:内核执行IO操作并返回。
    • 数据准备阶段:内核等待IO设备准备好数据
    • 数据拷贝阶段:将数据从内核缓冲区拷贝到用户空间缓冲区

 

二、阻塞IO模型

阻塞I/O模型是最常见的IO模型,其流程图如下所示。

 

应用程序发起一个系统调用(recvform),这个时候应用程序会一直阻塞下去,直到内核把数据准备好,并将其从内核复制到用户空间,复制完成后返回成功提示,这个时候应用程序才会继续处理数据。

  • 优点:模型简单,实现难度低,适用于并发量较小的应用开发。
  • 缺点:IO调用阶段和IO执行阶段都会阻塞。

典型的阻塞I/0模型的例子为data=socket.read(),如果内核数据没有准备就绪,Socket线程就会一直阻塞在read()中等待内核数据就绪。

生活场景:某天,你跟你女朋友去奶茶店买奶茶,点完奶茶后后,由于你们不知道奶茶什么时候才能做好,所以你们就只能一直等着,其他什么事情也不能干。

三、非阻塞 IO模型

在非阻塞IO模型中,应用进程需要不断询问内核数据是否就绪,在内核数据还未就绪时,应用进程还可以做其他事情。

 

从上图可以看出, 非阻塞IO模型需要应用进程不断地主动询问内核数据是否已准备好了。

  • 优点:模型简单,实现难度低;与阻塞IO模型对比,它在等待数据报的过程中,进程并没有阻塞,它可以做其他的事情。
  • 缺点:轮询发送 recvform,消耗CPU 资源。

生活场景:你和你女朋友去奶茶店买奶茶,吸取了上一次的教训,点完奶茶后顺便去逛了逛商场。由于你们担心会错过取餐,所以你们就每隔一段时间就来问下服务员,你们的奶茶做好了没有,来来回回好多回,若干次后,终于问到奶茶已经准备好了,然后你们就开心的喝了起来。

四、IO复用模型

非阻塞IO模型需要进程不断地轮询发起recvform系统调用,就会有很多的线程不断调用recvfrom 请求数据,先不说服务器能不能扛得住这么多线程,就算扛得住那么很明显这种方式是不是太浪费资源了,线程是我们操作系统的宝贵资源,大量的线程用来去读取数据了,那么就意味着能做其它事情的线程就会少。

例如:你是奶茶店的服务员,每个人点好奶茶后,每隔几分钟就来问你一次好了没有,随着问的人越来越多,你可能会开始怀疑人生。那么有没有什么好的解决办法呢?

答案:不需要所有进程轮询来发起recvform来查询数据是否已经准备好了,而是有人帮忙来询问,这个帮忙的人就是select。

IO复用模型如下所示:

 

多个进程的IO注册到一个复用器(select)上,select 会监听所有注册进来的IO。如果内核的数据报没有准备好,调用select 的进程将会被阻塞,而当任一IO在内核缓冲区中有数据,select调用就会返回可读条件,然后进程再进行recvform系统调用,内核将数据拷贝到用户空间,注意这个过程是阻塞的。

注意:IO 复用模型在第一个阶段和第二个阶段其实都有阻塞,第一个阶段阻塞于 select 调用,第二个阶段阻塞于数据复制。

  • 优点:适用于高并发应用程序。
  • 缺点:模型复杂,实现、开发难度较大。

生活场景:如果每个人都过一会就来问一下奶茶好了没有,奶茶店的压力也太大了。于是奶茶店想到了一个办法,找一个中间人(select)挡在奶茶店前面,顾客(应用进程)询问那个中间人奶茶好了没有(对应多个进程的IO注册到一个复用器(select)上),如果没有好就让顾客等待(应用进程阻塞于 select 调用)。中间人持续查看顾客的奶茶是否准备好,如果有一个人的奶茶准备好了就会去通知那个人可以取了(而当任一IO在内核缓冲区中有数据,select调用就会返回可读条件,然后进程再进行recvform系统调用)。

 

总结

学习IO模型时,必须要把每个模型联系起来看,比如阻塞IO模型会阻塞较长时间,而非阻塞IO在等待数据报的过程中,进程并没有阻塞,它可以做其他的事情。IO复用模型可以很好的降低服务器的压力,且在连接数众多且消息体不大的情况下有很大的优势。

来源:blog.csdn.net/qq_52173163/article/details/125932018

标签:IO,模型,阻塞,复用,内核,奶茶,select
From: https://www.cnblogs.com/zhangyi555/p/17451297.html

相关文章

  • 树莓派基于motion的usb摄像头监控
    一、准备免驱的usb摄像头都可以兼容。二、测试兼容  连接设备:1在终端输入:1.ls/dev查找,是否可以看见video0这个设备,如果有,说明树莓派已识别它了,如果没有,需要重新更新下固件,三、安装motionsudoaptinstallmotion四、配置文件配置motiondaemon 输入命令......
  • 各种@Conditional记录
    注解生效条件@ConditionalOnJava应用使用指定的Java版本时生效@ConditionalOnBean容器中存在指定的Bean时生效@ConditionalOnMissingBean容器中不存在指定的Bean时生效@ConditionalOnExpression满足指定的SpEL表达式时生效@ConditionalOnClass......
  • IDE 中登录 Github 报错 Invalid authentication data. 404 Not Found-Not Found.
    IDE中登录 Github 报错Invalidauthenticationdata.404NotFound-NotFound. 一、方法一使用token令牌进行身份验证(推荐)相对于使用账号密码,token令牌是一种更安全的身份验证方式。1、进入Github的token管理页面:https://github.com/settings/tokens如下图可见,我之前在ID......
  • IDE 中登录 Github 报错 Invalid authentication data. 404 Not Found-Not Found.
    IDE中登录 Github 报错Invalidauthenticationdata.404NotFound-NotFound. 一、方法一使用token令牌进行身份验证(推荐)相对于使用账号密码,token令牌是一种更安全的身份验证方式。1、进入Github的token管理页面:https://github.com/settings/tokens如下图可见,我之前在ID......
  • Move Zeroes 移动零、Expression Add Operators 表达式增加操作符
    1.MoveZeroes移动零 Givenanarray nums,writeafunctiontomoveall 0'stotheendofitwhilemaintainingtherelativeorderofthenon-zeroelements.Forexample,given nums=[0,1,0,3,12],aftercallingyourfunction, nums shouldbe [1,3,12,......
  • Provider parse errors: Cannot instantiate cyclic dependency! ApplicationRef ("[E
    异常: 异常的原因:自定义的一个全局异常类,在它的构造器中注入Router路由就抛出这个循环依赖的异常 解决方式:使用injector ......
  • kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future versi
    问题现象为通过kubectl进入pods时提示在未来版本中将移除这种进入这种方式,需要使用新的命令格式进入[root@master~]#kubectlexecmyweb-c5xq6-it/bin/bashkubectlexec[POD][COMMAND]isDEPRECATEDandwillberemovedinafutureversion.Usekubectlexec[POD]--......
  • asyncio:python3未来并发编程主流、充满野心的模块
    https://www.cnblogs.com/traditional/p/11828780.html楔子asyncio是Python在3.5版本中正式引入的标准库,这是Python未来并发编程的主流,非常重要的一个模块。有一个Web框架叫sanic,就是基于asyncio,使用sanic可以达到匹配Go语言的并发量(有点夸张了,还是有差距的,但......
  • ingress 调用istio ingress 控制器
    清理环境[root@k8s-master01httpbin]#  kubectldelete-fhttpbin-gateway1.yaml-nistiogateway.networking.istio.io"httpbin-gateway"deletedvirtualservice.networking.istio.io"httpbin"deleted[root@k8s-master01httpbin]#[root@k8s-master......
  • Template execution failed ReferenceError BASE_URL is not defined
    错误VueTemplateexecutionfailed:ReferenceError:BASE_URLisnotdefinedReferenceError:BASE_URLisnotdefined解决替换index.html替换前<linkrel="icon"href="<%=BASE_URL%>favicon.ico">替换后<linkrel="icon"......