基本IO模型理解

2018-06-20  本文已影响0人  執著我們的執著
写在前面

Linux网络编程中,经常被同步IO,异步IO,阻塞IO,非阻塞IO这些概念混淆!看了一篇博文,概念总结的很清晰。下面通过常见的IO模型来简单整理其中的区别和联系
参考并转载自 Euphie



常见的IO模型 :

[注] 统一使用Linux下的系统调用recv作为例子,它用于从套接字上接收一个消息,因为是一个系统调用,所以调用时会从用户进程空间切换到内核空间运行一段时间再切换回来。默认情况下recv会等到网络数据到达并且复制到用户进程空间或者发生错误时返回,而第4个参数flags可以让它马上返回。

1. 阻塞IO模型

使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。


白话: A同学用杯子接水,打开水龙头,不管当前水龙头有没有水,A一直等到杯子装满水才离开

注 :
接水处水龙头 ――― 内核
水 ――― 数据
非接水处 ――― 用户进程空间

2. 非阻塞IO模型

设flags为非阻塞参数 EWOULDBLOCK,让 recv不管有没有获取到数据都返回
具体:如果没有数据,则过一段时间再调用recv看看,如此循环,直至完成数据copy


白话 :
B同学也用杯子装水,打开水龙头后发现没有水,**离开接水处,过一会他又拿着杯子来看看……在中间离开的这些时间里,B同学离开了接水现场(离开内核,回到用户进程空间),可以做他自己的事情。这就是 非阻塞IO模型。但是他只是在 检查无数据的时候是非阻塞的,在 数据到达的时候依然要等待复制数据到用户空间(等着水将水杯装满), 因此它还是同步IO

3. IO复用模型

这里在调用recv前先调用select或者poll,这2个系统调用都可以在内核准备好数据(网络数据到达内核)时告知用户进程,这个时候再调用recv一定是有数据的。因此这一过程中它是阻塞于select或poll,而没有阻塞于recv,有人将非阻塞IO定义成在读写操作时没有阻塞于系统调用的IO操作(不包括数据从内核复制到用户空间时的阻塞,因为这相对于网络IO来说确实很短暂),如果按这样理解,这种IO模型也能称之为非阻塞IO模型,但是按POSIX来看,它也是同步IO,称之为同步非阻塞IO
这种IO模型比较特别,分个段。因为它能同时监听多个文件描述符(fd)。

白话:
C同学来装水,发现有一排水龙头,舍管阿姨告诉他这些水龙头都还没有水,等有水了告诉他。于是等啊等(select调用中),过了一会阿姨告诉他有水了,但不知道是哪个水龙头有水,自己看吧!于是C同学一个个打开,往杯子里装水(recv)。
注 : 顺便提下epoll(poll升级加强版),epoll也属于IO复用模型
主要区别在于:宿管阿姨会告诉C同学哪几个水龙头有水,不需要一个个打开看(当然还有其他的区别)

4. 信号驱动IO模型

通过调用sigaction注册信号函数,等内核数据准备好的时候系统中断当前程序,执行信号函数(在这里面调用recv)。


白话:
D同学让宿舍阿姨等有水时通知他(注册信号函数),没多久D同学得知有水了,跑去装水。是不是很像异步IO?很遗憾,它还是同步IO(因为并省不了装水的时间)。

5. 异步IO模型

调用aio_read,让内核等数据准备好,并且复制到用户进程空间后执行事先指定好的函数。


白话:
E同学让舍管阿姨将杯子装满水后通知他。整个过程E同学都可以做别的事情(没有recv),这才是真正的异步IO



总结

IO分两个阶段

一般来讲,阻塞IO模型,非阻塞IO模型,IO复用模型(select/poll/epoll),信号驱动IO模型都属于同步IO,因为阶段2都是阻塞的(虽然时间很短)
只有异步IO模型阶段1和阶段2都可以干别的事。

通过上面整理,可以区分何为同步和异步,何为阻塞和非阻塞。非阻塞并非异步……

上一篇下一篇

猜你喜欢

热点阅读