文档章节

【NIO系列】——之IO模型

wier
 wier
发布于 07/03 10:19
字数 2389
阅读 2851
收藏 72

这是【NIO系列】第二篇,欢迎持续关注:

【NIO系列】——之TCP探秘

上一篇我们讲到了关于TCP/IP协议的一些内容,这些是网络编程的必备知识。在了解NIO之前我们必须要了解一下对应的系统层IO模型,比如java的NIO对应是那种IO模型,阻塞和同步的差异在哪里,又是否相同。了解了这些更方便我们的后续的NIO探解。

一、同步、异步、阻塞、非阻塞

同步、异步,阻塞、非阻塞,这四种状态常有人分不清,主要是这四种状态的定义本身也不是很明确,所以各种解答的方式都有。常见的分类有以下:

  1. 同步阻塞IO

  2. 同步非阻塞IO

  3. 异步非阻塞IO

针对某种IO模型,我们如何分类,可以基于POSIX对同步/异步的定义来判别:

- A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;

- An asynchronous I/O operation does not cause the requesting process to be blocked;

那么从上我们可以看出:

阻塞:是否阻塞主要体现在调用的线程是否可以干别的,关注的是程序的等待状态

同步:是否同步体现在消息通信机制上 。

也就是说同步和异步说的是消息的通知机制,阻塞非阻塞说的是线程的状态 。

 

如果说以上的定义依然无法判别,我们可以从输入操作的两个阶段来看:

一般来说,一个输入操作通常包括两个不同阶段:

(1)等待数据准备好;(2)从内核向进程复制数据。

是否同步的判断依据是:是否针对的是整个过程,也就是2个阶段,是否有阻塞。

是否阻塞的判断依据是:按程序(线程)等待消息通知时的状态角度来说的,也就是主要是针对第一阶段来说。

 

举例

我们举例来说:

比如说做饭这件事,一般要分为连个步骤。

1、买菜,准备食材

2、炒菜,做出饭菜

 

方案一:自己动手处理。

1、去超市买菜,准备食材(阻塞,当前时段只能做一件事,且需要持续的等待)

2、回家切菜,炒菜,做出美味饭菜(阻塞,还是自己来处理)

评价: 方案一同步阻塞。首先阶段一是阻塞的,所以认定为阻塞,两个阶段都是阻塞的,认定为同步的。

 

方案二:盒马配送食材,自己做饭

1、网上下单,盒马配送食材,快递到了会敲门联系你。(非阻塞的,这期间你可以干其他事)

2、拿到菜,切菜、炒菜,做出美味饭菜(阻塞)

评价:方案二为同步非阻塞。阶段一为非阻塞,认定为非阻塞。阶段二为阻塞,两阶段中有一个为阻塞,认定为同步。

 

方案三:盒马配送,请阿姨做饭

1、网上下单,盒马配送食材,快递到了会敲门联系你。(非阻塞的,这期间你可以干其他事)

2、网上请阿姨小时工,帮忙做这一餐,做好通知我。(非阻塞,期间可以干其他事)

评价:方案三为异步非阻塞。阶段一为非阻塞,认定为非阻塞。阶段二非阻塞,则两阶段中都没有阻塞,认定为异步。

那么是否有异步阻塞IO模型,没有,要记得异步状态是包含二个阶段的,如果有阻塞的过程,为何还叫异步?

网上有很多介绍有异步阻塞模型的,我目前查到的资料还没有这个证明,若有找到相关论文,还请指教。目前我认为没有这个模型的。

 

二、Unix 5种I/O模型

《UNIX网络编程:卷一》的第六章书中列出了五种IO模型:

  • 阻塞式I/O;

  • 非阻塞式I/O;

  • I/O复用(select,poll,epoll...);

  • 信号驱动式I/O(SIGIO);

  • 异步I/O(POSIX的aio_系列函数);

1.阻塞式I/O

同步阻塞 IO 模型是最常用的一个模型,也是最简单的模型。在linux中,默认情况下所有的socket都是blocking。它符合人们最常见的思考逻辑。

在这个IO模型中,用户空间的应用程序执行一个系统调用(recvform),这会导致应用程序阻塞,什么也不干,直到数据准备好,等待kernel准备好从网络上接收到的数据报 + 等待收到的报文被从kernel复制到buf中,recvfrom方法才会返回,最后进程再处理数据。

这就是阻塞式IO模型

 

2.非阻塞式I/O

非阻塞IO时对一个非阻塞描述符循环调用recvfrom,持续的轮询(polling),以查看某个操作是否就绪。与阻塞IO不一样,"非阻塞将大的整片时间的阻塞分成N多的小的阻塞, 所以进程不断地有机会 '被' CPU光顾"。

非阻塞的recvform系统调用调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error。进程在返回之后,可以干点别的事情,然后再发起recvform系统调用。如此循环的进行recvform系统调用,检查内核数据,直到数据准备好,再拷贝数据到进程。拷贝数据整个过程,进程仍然是属于阻塞的状态

这就是非阻塞式IO模型

3.I/O复用

IO multiplexing就是我们说的select,poll,epoll 。为何叫多路复用,是因为它I/O多路复用可以同时监听多个fd,如此就减少了为每个需要监听的fd开启线程的开销。

select调用是内核级别的,可以等待多个socket,能实现同时对多个IO端口进行监听,当其中任何一个socket的数据准好了,就能返回进行可读然后进程再进行recvform系统调用,将数据由内核拷贝到用户进程,这个过程是阻塞的。

I/O复用模型会用到select、poll、epoll函数,这几个函数也会使进程阻塞,但是和阻塞I/O所不同的的,这几个函数可以同时阻塞多个I/O操作`。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时(不是等到socket数据全部到达再处理, 而是有了一部分数据就会调用用户进程来处理),才真正调用I/O操作函数。

IO复用有人把其成为同步非阻塞的,也有称为同步阻塞。其实这个是否阻塞还需要看第一个阶段,第一个阶段有的阻塞,有的不阻塞。主要也是阻塞在select阶段,属于用户主动等待阶段,我们且规范为阻塞状态,所以,把IO多路复用归为同步阻塞模式

这是IO复用的模型:

 

select、poll、epoll的不同

4.信号驱动式I/O

信号驱动式I/O:首先我们允许Socket进行信号驱动IO,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

也就是说第一个阶段,完全是非阻塞的,等数据到达会给一个信号通知,第二个阶段recvfrom还是阻塞过程,和之上无差异。

信号驱动式I/O 过程如下:

5.异步I/O

异步IO不是顺序执行,用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知IO两个阶段,进程都是非阻塞的

 

 

总结

针对这5中IO模型,我采用一张图来总结一下。

 

三、java IO

Unix中的五种I/O模型,除信号驱动I/O外,Java对其它四种I/O模型都有所支持。其中Java最早提供的blocking I/O即是同步阻塞I/O,而NIO即是同步非阻塞I/O,同时通过NIO实现的Reactor模式即是I/O复用模型的实现,通过AIO实现的Proactor模式即是异步I/O模型的实现。

所以说严格意义上来说,通过Reactor模式实现的NIO,和unix中的I/O多路复用是相同的概念,但这是一种编程模型,而不是原生支持。这也是我们下面所要进行的netty讲解的主要思想。

 

更多架构知识,欢迎关注我的公众号,大码候(cool_wier)

 

© 著作权归作者所有

共有 人打赏支持
wier
粉丝 750
博文 50
码字总数 134184
作品 0
东城
技术主管
私信 提问
加载中

评论(3)

cherry-pick
cherry-pick
netty那本书里面的吧。
丁富贵
我也看着眼熟
itfanr
itfanr
我在其他地方看过这篇文章了
【NIO系列】——之Netty

这是NIO系列的第四篇,欢迎继续关注: 【NIO系列】——之TCP探秘 【NIO系列】——之IO模型 【NIO系列】——之Reactor模型 如果你看过前面三篇文章,我们从最低层来分解NIO底层原理和使用方式,...

wier
07/31
0
0
【NIO系列】——之Reactor模型

在开篇之前,我们对JavaNIO 的使用方式不做过多介绍,这种API的介绍方式网上太多了,没必要详细介绍,我们假设NIO的使用方式,你能够熟练运用。这是NIO系列第三篇: 【NIO系列】——之TCP探秘...

wier
07/11
0
2
同步、异步、多线程与事件型综述

版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/8867174 同步、异步、多线程与事件型综述作者:chszs,转载需注明。博客主页:...

chszs
2013/04/29
0
0
深入浅出:进程、线程、协程、同步、异步、回调

一、上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术。 不过首先说明一点术语。当我们说“上下文”的时候,指的是程序在执行中的一个状态。通常我们会用调用栈来表示...

follitude
2016/09/26
77
0
httpd2.2实现httpd服务

httpd的版本: httpd-1.3:官方已经停止维护;超级稳定 httpd-2.0: httpd-2.2: httpd-2.4: httpd的具体的特性: 高度模块化:Core + Modules DSO:Dynamic Shared Object,动态共享对象;...

圣伯纳v
2017/08/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

TiQuery:All Diagnosis in SQL | TiDB Hackathon 优秀项目分享

本文作者是来自 TiNiuB 队的黄梦龙同学,他们的项目 TiQuery 在本届 TiDB Hackathon 2018 中获得了三等奖。 TiQuery 可以搜集诊断集群问题所需要的信息,包括集群拓扑,Region 分布,配置,各...

TiDB
7分钟前
1
0
git 分支创建合并流程图

gentlelions
15分钟前
1
0
Kali Linux常用服务配置教程DHCP服务原理

Kali Linux常用服务配置教程DHCP服务原理 动态主机配置协议(Dynamic Host Configuration Protocol,简称DHCP)是一个局域网的网络协议,基于UDP协议工作。它主要有两个用途:第一,给内部网...

大学霸
16分钟前
0
0
控制台打印图片

function dev(){ if (window.console){ console.log("%c\n ", "font-size:100px;background:url('http://gmcyzs.com/resources/images/logo.png') no-repeat"); console.log('%c 深务平台,\......

羊皮卷
24分钟前
0
0
MyBaties的二级缓存

二级缓存介绍 在上文中提到的一级缓存中,其最大的共享范围就是一个SqlSession内部,那么如何让多个SqlSession之间也可以共享缓存呢,答案是二级缓存。 当开启二级缓存后,会使用CachingExec...

嘴角轻扬30
24分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部