IO复用-阻塞IO-非阻塞IO-同步IO-异步IO

Wesley13
• 阅读 877

本文是对《UNIX网络编程卷1》第6章的总结。

一、            什么是IO复用?

它是内核提供的一种同时监控多个文件描述符状态改变的一种能力;例如当进程需要操作多个IO相关描述符时(例如服务器程序要同时查看监听socket和大量业务socket是否有数据到来),需要内核能够监控这许多描述符,一旦这些描述符有就绪(或者状态改变了)就告诉主动告诉进程哪些描述符已经就绪,这样站在进程的角度,就不需要挨个的查看每个描述符是否就绪。

二、            IO操作分为两个阶段:

(1)      准备阶段,例如输入操作时要等待数据已经就绪,输出操作时缓冲区中有空间可供使用;

(2)      数据拷贝阶段,例如输入操作时将数据从内核复制到用户缓存,输出操作时将用户缓存复制到内核。

以读取系统调用recvfromfrom为例,每当用户进程发起一个recvfrom操作,站在用户进程的角度,其实它包含上述两个请求:第一个请求就是看看数据是不是准备好了,如果没有准备好就把我阻塞那里(对应阻塞IO)或者给我返回个没有准备好的标志(对应非阻塞IO);第二个请求就是在数据就绪的时候将数据拷贝给用户进程。

三、            Unix环境下有5中IO模型

(1)阻塞IO模型

(2)非阻塞IO模型

(3)IO复用模型

(4)信号驱动IO模型

(5)异步IO模型

其中(1)~(4)都属于同步IO,(5)属于异步IO,因为前4中模型在第一阶段的准备阶段有区别,在第二阶段的数据拷贝过程中都会阻塞用户进程,而(5)在第一阶段的准备阶段和第二阶段的数据拷贝过程都不会阻塞用户进程。

四、            各种模型的详细区别

(1)      阻塞IO模型

阻塞IO模型中,以数据接收为例,进程调用recvfrom系统调用向内核请求读取数据,其内部过程将如下图1所示:

IO复用-阻塞IO-非阻塞IO-同步IO-异步IO

图1阻塞IO模型

由图1可以看到用户进程从发起recvfrom系统调用开始后的两个阶段都被阻塞。

(2)      非阻塞IO模型

以读取数据为例,非阻塞模型中,进程需要先把socket设置为非阻塞模式,这样内核在准备数据时就不会阻塞该系统调用,而是直接返回EWOULDBLOCK,在读取操作时,用户进程一样是调用recvfrom向内核请求数据,其内部过程如下图2所示:

IO复用-阻塞IO-非阻塞IO-同步IO-异步IO

图2 非阻塞模式IO模型

由上图2可以看到非阻塞模式中,在数据准备阶段,系统调用不会被阻塞,但是在数据复制阶段也会被阻塞;因此这里所说的阻塞是指数据准备阶段是否被阻塞,而不是数据拷贝阶段。

(3)      IO复用模型

IO复用模型中,进程可以让内核监控多个描述符的就绪状态,一般使用的接口函数为select或者poll,内核通过select查询到所监控的描述符中有就绪的,则把就绪的描述符返回给调用进程,进程再调用recvfrom实际读取数据,其内部过程大致如下图3所示:

IO复用-阻塞IO-非阻塞IO-同步IO-异步IO

图3 、IO复用模型

由上图可以看出,在IO复用模型中,用户进程先调用select或者poll查看是否有数据就绪,如果有数据就绪再调用recvfrom去读取数据,系统在阶段1和阶段2都将会被阻塞,但是阻塞于不同的系统调用(阶段1阻塞于select或者poll,阶段2阻塞于recvfrom)。

(4)      信号驱动IO模型

信号驱动IO模型是让内核在描述符就绪时发送SIGIO信号通知用户进程。在使用信号驱动模型进行IO操作时,首先要打开socket使用信号驱动IO的能力;然后调用sigaction系统调用设置信号SIGIO的处理函数,sigaction系统调用不会被阻塞。这样就可以在信号处理函数中读取数据了,其处理过程如下图4所示:

IO复用-阻塞IO-非阻塞IO-同步IO-异步IO

图4 信号驱动IO模型

由上图4可以看出,信号驱动模型只要设置好信号处理函数后就可以进行其他操作了,当有数据到来时内核将会通知进程进行处理;与非阻塞IO模型相比,信号驱动IO模型不需要在准备数据时轮询是否准备好。

(5)      异步IO模型

异步IO模型中,用户进程发起读取调用之后会立即返回,待内核接收到数据并将数据拷贝到用户进程空间之后,再通知用户进程,其过程如下图5所示:

IO复用-阻塞IO-非阻塞IO-同步IO-异步IO

图5异步IO模型

五、5中IO模型的比较

上述5中IO操作模型的区别可以参见图6所示:

IO复用-阻塞IO-非阻塞IO-同步IO-异步IO

图6、5中IO模型的比较

同步IO:导致请求进程阻塞,直到IO操作完成;

异步IO:不导致请求阻塞;

因此,前面介绍的5中模型中,前4中IO模型都属于同步IO,因为他们第二阶段的复制数据过程将阻塞用户进程,只有第5种才是真正的异步IO模型。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Linux的文件描述符
(1).文件描述符的定义  文件描述符是内核为了高效管理已被打开的文件所创建的索引,用于指向被打开的文件,所有执行I/O操作的系统调用都通过文件描述符;文件描述符是一个简单的非负整数,用以表明每个被进程打开的文件。程序刚刚启动时,第一个打开的文件是0,第二个是1,以此类推。也可以理解为文件的身份ID。  用户通过操作系统处理信息的过程中,使用的交互设
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这