首页 > 系统相关 >Linux的IO模型

Linux的IO模型

时间:2023-05-02 15:05:20浏览次数:43  
标签:模型 阻塞 用户 内核 IO Linux 进程 数据

一、基本概念

五种IO模型包括:阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO。

首先需要了解下系统调用的几个函数和基本概念。

1.1 简单介绍几个系统调用函数

由于我对于C语言不熟悉,几个系统函数参考了一些文章,如果错误欢迎指出!

recvfrom

Linux系统提供给用户用于接收网络IO的系统接口。从套接字上接收一个消息,可同时应用于面向连接和无连接的套接字。

如果此系统调用返回值<0,并且 errno为EWOULDBLOCK或EAGAIN(套接字已标记为非阻塞,而接收操作被阻塞或者接收超时 )时,连接正常,阻塞接收数据(这很关键,前4种IO模型都设计此系统调用)。

select

select系统调用允许程序同时在多个底层文件描述符上,等待输入的到达或输出的完成。以数组形式存储文件描述符,64位机器默认2048个。当有数据准备好时,无法感知具体是哪个流OK了,所以需要一个一个的遍历,函数的时间复杂度为O(n)。

poll

以链表形式存储文件描述符,没有长度限制。本质与select相同,函数的时间复杂度也为O(n)。

epoll

是基于事件驱动的,如果某个流准备好了,会以事件通知,知道具体是哪个流,因此不需要遍历,函数的时间复杂度为O(1)。

sigaction

用于设置对信号的处理方式,也可检验对某信号的预设处理方式。Linux使用SIGIO信号来实现IO异步通知机制。

1.2 同步&异步

同步和异步是针对应用程序和内核交互而言的,也可理解为被被调用者(操作系统)的角度来说。同步是用户进程触发IO操作并等待或轮询的去查看是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知,需要CPU支持

1.3 阻塞&非阻塞

阻塞和非阻塞是针对于进程在访问数据的时候,也可理解为调用者(程序)角度来说。根据IO操作的就绪状态来采取的不同的方式。阻塞方式下读取或写入方法将一直等待,而非阻塞方式下读取或写入方法会立即返回一个状态值。

下午撸代码饿了,好久没吃KFC了,决定去整个全家桶 ,这一切都要从一个全家桶说起~

Linux的IO模型_阻塞IO

我跑去肯德基买全家桶,但是很不巧,轮到我时,全家桶卖完了,我只能等着新做一份 ...

二、阻塞IO模型

学习过操作系统的知识后,可以知道:不管是网络IO还是磁盘IO,对于读操作而言,都是等到网络的某个数据分组到达后/数据准备好后,将数据拷贝到内核空间的缓冲区中,再从内核空间拷贝到用户空间的缓冲区。

此时我已饥渴难耐,全程盯着后厨,等待着一分一秒(别多想 ),终于全家桶做好了,在此期间虽然什么事也没干,但是最后能吃到全家桶,我很幸福。此处需要一个清新的脑回路,我就是程序,我想要全家桶,于是发起了系统调用,而后厨加工的过程就是在做数据准备和拷贝工作。全家桶最终到手,数据终于从内核空间拷贝到了用户空间。

简单看下执行流程:

Linux的IO模型_阻塞IO_02

接下来发挥看图说话的专长了:阻塞IO的执行过程是进程进行系统调用,等待内核将数据准备好并复制到用户态缓冲区后,进程放弃使用CPU并一直阻塞在此,直到数据准备好。

三、非阻塞IO模型

此时我每隔5分钟询问全家桶好了没,在数次盘问后,终于出炉了。在每一次盘问之前,对于程序来说是非阻塞的,占用CPU资源,可以做其他事情。

每次应用程序询问内核是否有数据准备好。如果就绪,就进行拷贝操作;如果未就绪,就不阻塞程序,内核直接返回未就绪的返回值,等待用户程序下一个轮询。

Linux的IO模型_阻塞IO_03

大致经历两个阶段:

  • 等待数据阶段:未阻塞, 用户进程需要盲等,不停的去轮询内核。
  • 数据复制阶段:阻塞,此时进行数据复制。在这两个阶段中,用户进程只有在数据复制阶段被阻塞了,而等待数据阶段没有阻塞,但是用户进程需要盲等,不停地轮询内核,看数据是否准备好。

四、IO多路复用模型

排了很长的队,终于轮到我支付后,拿到了一张小票,上面有号次。当全家桶出炉后,会喊相应的号次来取。KFC营业员小姐姐打小票出号次的动作相当于操作系统多开了个线程,专门接收客户端的连接。我只关注叫到的是不是我的号,因此程序还需在服务端注册我想监听的事件类型。

多路复用一般都是用于网络IO,服务端与多个客户端的建立连接。下面是神奇的多路复用执行过程:

Linux的IO模型_Linux运维_04

相比于阻塞IO模型,多路复用只是多了一个select/poll/epoll函数。select函数会不断地轮询自己所负责的文件描述符/套接字的到达状态,当某个套接字就绪时,就对这个套接字进行处理。select负责轮询等待,recvfrom负责拷贝。当用户进程调用该select,select会监听所有注册好的IO,如果所有IO都没注册好,调用进程就阻塞。

对于客户端来说,一般感受不到阻塞,因为请求来了,可以用放到线程池里执行;但对于执行select的操作系统而言,是阻塞的,需要阻塞地等待某个套接字变为可读。

IO多路复用其实是阻塞在select,poll,epoll这类系统调用上的,复用的是执行select,poll,epoll的线程。

五、信号驱动IO模型

跑KFC嫌麻烦,刚好有个会员,直接点份外卖,美滋滋。当外卖送达时,会收到取餐电话(信号)。在收到取餐电话之前,我可以愉快地吃鸡或者学习。

当数据报准备好的时候,内核会向应用程序发送一个信号,进程对信号进行捕捉,并且调用信号处理函数来获取数据报。

Linux的IO模型_阻塞IO_05

该模型也分为两个阶段:

  • 数据准备阶段:未阻塞,当数据准备完成之后,会主动的通知用户进程数据已经准备完成,对用户进程做一个回调。
  • 数据拷贝阶段:阻塞用户进程,等待数据拷贝。

六、异步IO模型

此时科技的发展已经超乎想象了,外卖机器人将全家桶自动送达并转换成营养快速注入我的体内,同时还能得到口感的满足。注入结束后,机器人会提醒我注入完毕。在这个期间我可以放心大胆的玩,甚至注射的时候也不需要停下来!

类比一下,就是用户进程发起系统调用后,立刻就可以开始去做其他的事情,然后直到I/O数据准备好并复制完成后,内核会给用户进程发送通知,告诉用户进程操作已经完成了。

Linux的IO模型_Linux运维_06

特点:

  1. 异步I/O执行的两个阶段都不会阻塞读写操作,由内核完成。
  2. 完成后内核将数据放到指定的缓冲区,通知应用程序来取。

总结

从效率上来说,可以简单理解为阻塞IO<非阻塞IO<多路复用IO<信号驱动IO<异步IO。从同步和异步来说,只有异步IO模型是异步的,其他均为同步。


本文学习自https://zhuanlan.zhihu.com/p/127170201

标签:模型,阻塞,用户,内核,IO,Linux,进程,数据
From: https://blog.51cto.com/jowin/6239950

相关文章

  • 中台设计- 业务中台设计模型(5/5)
    中心三层模型0级功能架构图0级技术架构图0级业务数据流图1级功能架构图业务建模功能需求汇总功能抽象汇总系统应用一级功能二级功能功能说明业务领域业务实体领域能力订单管理订单列表订单列表交易域订单生成订单订单发货库存域面单查询面单......
  • [Javascript] avoid mutation: Array.prototype.toSpliced() vs splice()
    Array.prototype.splice()mutatestheoriginalarray.Toavoidmutation,weuseArray.prototype.slice().newmethodArray.prototype.toSpliced()returnanewarraytoavoidthemutation.constmonths=["Jan","Mar","Apr",&quo......
  • [Javascript] Avoid mutation, Array.prototype.toSorted() vs sort()
    sort(),mutatestheoriginalarray,andreturnthereferencetooriginalarrayandsorted.The toSorted() methodof Array instancesisthe copying versionofthe sort() method.Itreturnsanewarraywiththeelementssortedinascendingorder.const......
  • Linux下如何启动、关闭Nginx?
    Linux下如何启动、关闭Nginx?Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势,下面为大家分享一下Linux下启动、关闭Nginx具体方法。Linux下启动、关闭Nginx先决条件:安装并配置了Nginx的系统访问终端窗口或命令行具有sudo或roo......
  • [Javascript] Avoid mutation, Array.prototype.toReversed() vs reverse()
    reverse()mutatestheoriginalarray,returnthereferencepointtotheoriginalarray.The toReversed() methodof Array instancesisthe copying counterpartofthe reverse() method.Itreturnsanewarraywiththeelementsinreversedorder.constite......
  • 解决Matlab在Linux下无法使用hardware OpenGL的问题
    解决Matlab在Linux下无法使用hardwareOpenGL的问题1报错信息在命令行使用命令matlab-nodesktop-nosplash启动Matlab时,出现如下报错:MATLABisselectingSOFTWAREOPENGLrendering.在查阅ArchWikiMatlabOpenGLAcceleration栏目后,发现这是因为Matlab未启用OpenGL硬件加......
  • linux安装jdk1.8
    为防止操作权限不足,建议切换root用户,当然如果你对Linux命令熟悉,能够自主完成权限更新操作,可以不考虑此推荐。环境:centos7.6ssh连接工具:tabby(自从用了这个工具,我再也不用xshell了,这个工具自带文件上传,还有网页版)创建目录mkdir/opt/jdk把jdk的压缩包上传到/opt/jdk......
  • 软件工程师能力模型探讨
    软件工程师能力模型探讨高级JAVA工程师通用技能ExpertJavaknowledge  JAVA知识专家级Object-OrientedDesignPatterns  面向对象与设计模式High-leveldesignskills  高层模块设计Designingforspecificrequirements(e.g.security,scalability,optimization) ......
  • Book-Linux/UNIX 系统编程手册-上册(部分章节)
    Book-Linux/UNIX系统编程手册-上册(部分章节)Linux的广受欢通只是原因之一,而有时出于性能方面的考虑,或是需要访问标准UNIX编程接口所不支持功能时,使用非标准扩展(正因如此,所有UNIX实现都提供有非标准扩展)就显得至为重要综上所述,在构思本书时,作者不但力图使其对在各种UNIX实现中......
  • 如何将input里面的数值传输到servlet后台(利用vue+axios实现)
    相关步骤1、为input输入框加一个属性v-model2、并相应设置一个button3、vue里面的data定义上这个v-model值4、因为获取到了相关的数值,需要将其传递到后台,用post方式5、定义我们需要传递到url的数据完成!......