五大I/O模型详解

原创
2016/07/08 18:45
阅读数 2.5K

前文

同步与异步&阻塞与非阻塞中,简要的介绍一些基础概念,但这些概念最终是为IO所服务,是为文件所服务。按照Linux一句话来说,一切皆文件。

一、Unix IO模型

Unxi大师Richard Stevens在 UNIX® Network Programming 中讲述了五种I/O 模型

  • blocking IO
  • nonblocking IO
  • IO multiplexing
  • signal driven IO
  • asynchronous IO

而本文也是基于这五种I/O模型,以及交叉着同步与异步&阻塞与非阻塞的概念。但在探讨I/O模型之前,先要了解一下I/O模型发生的对象和步骤。

对于一个文件IO的操作(这里以read为例子),会涉及到两个对象:

  • 一个是调用这个IO的进程process
  • 另外一个就是系统内核kernel

当一个read操作发生时,会经历两个阶段

  • 进程等待内核数据准备(Waiting for the data to be ready)
  • 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)

二、五大I/O模型

1.blocking IO(阻塞IO)

1.1 概念介绍

image

在默认情况下,所有的IO操作都是blocking io,流程如上图所示,步骤为:

  • 1、应用进程(application process) 调用了recvfrom这个系统调用
  • 2、然后内核(kernel)开始了IO的第一个阶段:准备数据。在内核准备数据期间,应用进程是一直阻塞的。(Waiting for the data to be ready)
  • 3、内核准备好数据之后,把数据从内核copy到应用内存。在内核copy数据期间,应用进程依然是一直阻塞的。(Copying the data from the kernel to the process)
  • 4、内核返回结果,应用进程才解除block的状态,重新继续执行

1.2 场景比喻

又到了小明买奶茶的时候了。如果不知道小明买奶茶的故事,点这里

小明去买奶茶,可能会有两种方式:

  • 小明点单交钱,然后等着取奶茶;
  • 小明点单交钱,然后奶茶妹给了小明一个小票,等小明的奶茶做好了,再告诉小明来取;

现在【小明点单交钱,然后等着取奶茶】升级一点情节,变成了如下方式:

  • 小明点单交钱,然后等着奶茶妹做奶茶,等着奶茶妹把奶茶给他

这样就变成了这样:

  • 对比blockingIO模型,小明就是应用进程(application process),奶茶妹就是内核(kernel)
  • 小明点单交钱就是就是调用recvfrom
  • 奶茶妹做奶茶,就是(Waiting for the data to be ready)
  • 奶茶妹把奶茶给小明,就是(Copying the data from the kernel to the process)

1.3 blockingIO总结

blocking IO的特点就是在IO执行的两个阶段都阻塞了,而blocking IO整个过程也是同步模型,所以blocking IO可以叫做同步阻塞IO

2.non-blocking IO(非阻塞IO)

2.1 概念介绍

image

非阻塞IO与阻塞不同点在于不断的查询数据是否准备好,如上图所示,流程为:

  • 1、应用进程(application process) 调用了recvfrom这个系统调用
  • 2、内核告诉应用进程,数据还没有准备好
  • 3、应用进程发现数据没有准备好,不停的调用recvfrom这个系统调用,内核在数据没有准备好的情况下不停的告诉应用进程数据没有准备好。妈的智障
  • 4、内核准备数据。这个过程中,应用进程没有阻塞,因为它在不停的调用!(Waiting for the data to be ready)
  • 5、在应用进程不停的调用中,恰好这次内核把数据准备好了,然后内核把数据copy到应用进程内存。在内核copy数据期间,应用进程是一直阻塞的。(Copying the data from the kernel to the process)
  • 6、内核返回结果,应用进程解除block的状态,重新继续执行

2.2 场景比喻

现在【小明点单交钱,然后等着取奶茶】升级成了下面情节,变成了如下方式:

  • 小明点单交钱,奶茶妹说我这就给你做奶茶,还没好,你等会。
  • 不到3秒钟,小明就问奶茶好了没有,奶茶妹说还没有哦。又过了3秒钟小明又问奶茶好没有,奶茶妹说没有哦。
  • 问了不知道多少次之后,奶茶妹此时终于做好了奶茶,然后把奶茶交到小明手里
  • 奶茶妹说了一句,你的奶茶好了,滚!

2.3 总结

nonBlocking IO模型中,数据准备阶段并没有阻塞,因为应用进程不断的查询内核数据是否准备完毕,并没有被阻塞,实际上应用进程可以在这时干其他事情。在数据复制阶段阻塞。

non-blocking IO模型就不能理解为同步非阻塞模式了,但是也不能理解为异步非阻塞模式,算是同步和异步的一个混合体。

3. IO multiplexing(多路复用)

3.1 概念介绍

IMAGE

多路复用听上去比较难理解,但对应linux的select,poll就好理解了,如上图所示,流程为:

  • 1、应用进程(application process) 调用了select这个系统调用
  • 2、内核开始准备数据。在内核准备数据期间,应用进程是一直阻塞的。(Waiting for the data to be ready)
  • 3、内核告诉应用进程数据准备好了
  • 4、应用进程(application process) 调用了recvfrom这个系统调用
  • 5、内核把数据copy到应用进程内存。在内核copy数据期间,应用进程是一直阻塞的。(Copying the data from the kernel to the process)
  • 6、内核返回结果,应用进程解除block的状态,重新继续执行

咋一看,咦,好像和blockingIO差不多,而且还多了一步调用。那优缺点在哪里呢?

  • 当用户进程调用了select,内核监视这个IO请求
  • 当N个用户进程调用了select,内核监视N个IO请求
  • 有一个用户进程的IO数据准备好了,内核告诉该用户进程数据准备好了,来取吧
  • 所以优点就在于内核可以多监视更多的IO请求,可以同时处理多个connection(多说一句。所以,如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)
  • 在IO multiplexing Model中,如上图所示,整个用户的process其实是一直被block的,只不过process是被select这个函数block,而不是被socket IO请求给block。这句很重要。
  • 实际中,对于每一个socket,一般都设置成为non-blocking,轮训的时机设计好,才能体现出该IO设计模型的优势。

3.2 场景比喻

现在【小明点单交钱,然后等着取奶茶】升级成了下面情节,变成了如下方式:

  • 小明点单交钱
  • 然后奶茶妹开始做奶茶
  • 奶茶妹做好奶茶之后,告诉小明过来取奶茶
  • 小明取奶茶
  • 奶茶妹把奶茶交到小明手里
  • 小明离开

3.3总结

IO multiplexing优点在于内核可以处理多个IO请求。一般会运用非阻塞IO和IO multiplexing进行组合。

4. signal driven I/O(信号IO)

4.1 概念介绍

IMAGE

信号模型比较简单,如下流程:

  • 应用进程发起一个信号,告诉内核说我需要什么文件,然后立马返回
  • 内核准备数据。应用进程该干嘛干嘛,不会阻塞。
  • 内核准备好数据,告诉应用进程来取数据
  • 应用进程请求取数据
  • 内核把数据复制到应用进程。应用进程阻塞。
  • 返回数据

4.2 场景比喻

现在【小明点单交钱,然后等着取奶茶】升级成了下面情节,变成了如下方式:

  • 小明点单交钱,奶茶妹给小明一个小票
  • 然后奶茶妹开始做奶茶
  • 奶茶妹做好奶茶之后,告诉小明过来取奶茶
  • 小明取奶茶
  • 奶茶妹把奶茶交到小明手里
  • 小明离开

4.3 总结

信号驱动IO模型,就可以为异步阻塞IO模型。

5. asynchronous I/O(异步非阻塞)

5.1 概念介绍

IMAGE

流程如下:

  • 应用进程发起一个信号,告诉内核说我需要什么文件,然后立马返回
  • 内核准备数据。应用进程该干嘛干嘛,不会阻塞。
  • 内核把数据copy到应用进程内存。应用进程该干嘛干嘛,不会阻塞。
  • 返回数据

有没有碉堡了的感觉,linux aio就是这种模型

5.2 场景比喻

现在【小明点单交钱,然后等着取奶茶】升级成了下面情节,变成了如下方式:

  • 小明点单交钱,奶茶妹给小明一个小票
  • 然后奶茶妹开始做奶茶
  • 奶茶妹做好奶茶之后,把奶茶递到小明手里。次奥这么好待遇
  • 小明拿到奶茶,小明离开

5.3 总结

异步非阻塞IO,应用进程两个阶段都不会阻塞。简直完美。

三、大总结

  • blocking I/O,数据准备、数据copy 全阻塞,同步阻塞IO
  • nonblocking I/O,数据准备不阻塞,数据copy阻塞,非阻塞IO
  • I/O multiplexing,数据准备阻塞,数据copy阻塞,多路复用IO,优点可以支持更多IO请求
  • signal driven I/O (SIGIO),数据准备不阻塞,数据copy阻塞,异步阻塞IO
  • asynchronous I/O,数据准备、数据copy 全部阻塞。异步非阻塞IO

#文章引用 I/O Models

展开阅读全文
打赏
8
103 收藏
分享
加载中
haoran_10博主

引用来自“黄开源中国”的评论

恩是我看错了。只是比较相似,没完全一样。https://www.zhihu.com/question/19732473原文链接。里面也有很多引用
呵呵,我是从篇文章借鉴的,http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch06lev1sec2.html
2016/07/13 16:45
回复
举报
恩是我看错了。只是比较相似,没完全一样。https://www.zhihu.com/question/19732473原文链接。里面也有很多引用
2016/07/13 11:12
回复
举报
haoran_10博主

引用来自“黄开源中国”的评论

文章是转载的吧?之前看过一模一样的。。如果是转载还请尊重版权
哇,居然还有一模一样的,太巧了
2016/07/12 19:09
回复
举报
文章是转载的吧?之前看过一模一样的。。如果是转载还请尊重版权
2016/07/12 18:35
回复
举报
更多评论
打赏
4 评论
103 收藏
8
分享
返回顶部
顶部