点击上方“罗晓胜”,马上关注,您的支持对我帮助很大

 

/   前言   /

 

还有不知道5种IO模型的吗

5种IO模型:

  • 阻塞I/O(blocking IO)

  • 非阻塞I/O(noblocking IO)

  • I/O复用    (IO multiplexing )

  • 信号驱动I/O (signal driven IO)

  • 异步I/O (asynchronous IO)

IO分两阶段:

1.数据准备阶段

2.内核空间复制回用户进程缓冲区阶段

 一般来讲:阻塞IO模型、非阻塞IO模型、IO复用模型(select/poll/epoll)、信号驱动IO模型都属于同步IO,因为阶段2是阻塞的(尽管时间很短)。只有异步IO模型是符合异步IO操作含义的,不管在阶段1还是阶段2都可以干别的事。

 

/   正文   /

 

 ▊ 5种IO模型解析:

 

blocking IO(BIO)           阻塞IO:

blockingIO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。

 

使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。打个比方,A同学排队买票,他只能排队买上票才可以离开。这一过程就可以看成使用了阻塞       IO模型,因为如果在没买到票之前,他不能离开队伍做别的事情(离开等于白排队,回来又要重新排队)。很显然这种,I/O模型是同步的。

 

nonblocking IO(NIO)      非阻塞IO:

在非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有。

在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象

NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法

改变flags,让recv不管有没有获取到数据都返回,如果没有数据那么一段时间后再调用recv看看,如此循环。对比阻塞模型,相当于A同学买票过程中,采用了取号买票,再没有到他前,他可以不断的返回购票大厅看下是不是到了自己的号,中间的过程可以做其他事情。他就不用向之前一样一刻不能离开购票大厅。这就是非阻塞IO模型。但是它只有是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间(到自己的号买上票),因此它还是同步IO。

 

IO multiplexing      IO多路复用:

select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。

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

    这种IO模型比较特别,分个段。因为它能同时监听多个文件描述符(fd)。举例A同学来北京到南京的车票,发现有一排售票窗口,售票服务人员告诉他这些窗口目前没有票,等有票告诉他。于是等啊等(select调用中),过了一会售票服务人员告诉他有票了,但不知道是哪个窗口卖北京到南京的车票,自己看吧。于是A同学一个个窗口问,直到找到卖北京到南京车票的窗口买上票(recv)。这里再顺便说说鼎鼎大名的epoll(高性能的代名词啊),epoll也属于IO复用模型,主要区别在于售票服务人员告诉他A同学哪几个窗口卖北京到南京的车票,不需要一个个去问了。

 

signal driven IO     信号驱动IO(在实际中并不常用):

通过调用sigaction注册信号函数,等内核数据准备好的时候系统中断当前程序,执行信号函数(在这里面调用recv)。A同学让舍售票服务人员等有票的时候通知他(注册信号函数),    没多久A同学得知有票了,跑去买票。是不是很像异步IO?很遗憾,它还是同步IO(省不了买票的时间啊)。

 

asynchronous IO    异步IO:

AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型

     调用aio_read,让内核等数据准备好,并且复制到用户进程空间后执行事先指定好的函数。A同学让售票服务人员帮他买好票后通知他。整个过程A同学都可以做别的事情(没有           recv),这才是真正的异步IO。

 

 ▊ select/epoll

select/epoll,大概就都能明白了。有些地方也称这种IO方式为事件驱动IO(event driven IO)。我们都知道,select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。它的流程如图:

在多路复用模型中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

    结论:select的优势在于可以处理多个连接,不适用于单个连接

 

 

 

 ▊ select、poll、epoll之间的区别

(1)select==>时间复杂度O(n)

它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。

 

(2)poll==>时间复杂度O(n)

 

(3)epoll==>时间复杂度O(1)

Linux下多路复用IO接口select/poll的增强版本

epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们。所以我们说epoll实际上是事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))


 

/   总结   /

还有不知道5种IO模型的吗

还有不知道5种IO模型的吗

 

往期推荐:

MySQL  百万级数据量分页查询方法及其优化

看完这篇,Redis你就全懂了

如何自学Android

如何入门做软件开发

为什么我不推荐入行程序员

做全栈开发很难吗

 

欢迎关注我的公众号

学习技术或投稿

 

还有不知道5种IO模型的吗

长按上图,识别图中二维码即可关注

 

相关文章:

  • 2021-11-29
  • 2021-08-10
  • 2021-10-13
  • 2021-10-01
  • 2021-12-29
  • 2021-07-05
  • 2021-05-23
猜你喜欢
  • 2021-08-25
  • 2022-12-23
  • 2021-05-26
相关资源
相似解决方案