IO浅谈

首先

我们在谈及IO模型的时候,就必须要引入一个“操作系统”级别的调度者-系统内核(kernel),而阻塞非阻塞是跟进程/线程严密相关的,而进程/线程又是依赖于操作系统存在的,所以自然不能脱离操作系统来讨论阻塞非阻塞。同步/异步也是跟任务流相关的,所以要全面理解就必须考虑到并发的任务流,不然,肯定很难举出恰当的例子的。

本文讨论的背景是Linux环境下的network IO。
本文最重要的参考文献是Richard Stevens的“UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”,6.2节“I/O Models ”,Stevens在这节中详细说明了各种IO的特点和区别,如果英文够好的话,推荐直接阅读。Stevens的文风是有名的深入浅出,所以不用担心看不懂。本文中的流程图也是截取自参考文献。

在网络并发编程中,通俗的讲IO分为两个东西:1、等待 ==> 2、数据搬迁

或者这样说:当IO发生时,会涉及到对象和步骤,当进行网络IO(Network IO)时候,必须涉及到两个系统对象,一个不可避免的就是产生这个IO的进程或者线程(process or thread),还有另外一个老大级人物:系统内核(kernel),至于为何要让老大出场处理IO,究其原因就是,比如我们在进行读操作的时候,进程或线程是无法直接跟硬件打交道,无法直接从硬盘中直接拿到我们想要的数据,而是需要系统内核取帮我们去取,它取需要过程,有过程我们就得等待,系统内核取到了先会将数据放进它自己的内存空间中,我们要取还得从它的内存空间把数据迁移到进程的内存空间,这才算真正地拿到数据。

通俗的讲就是:

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

1)等待数据准备(Waiting for the data to be ready)

2)将数据从内核拷贝到进程(线程所在的)的内存中(Copying the data from the kernel to the process or thread)

四个概念

同步 synchronous

一个进程或线程在提交任务或发出调用后,要等待返回的最终结果后才算执行完毕,然后才会继续执行下一步操作

所谓同步,就是没得到最终结果之前,就不会继续下一步操作。
这就好比单行道过收费站一样,一个接着一个,只有上一个结束收费下一辆车才能开始进入站窗口交费。每辆车就相当与一个进程或线程。
其实绝大多数的函数都是同步调用,我们都是拿到结果之后在进行下一步代码操作。

而我们在谈及同步和异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。

异步 asynchronous

异步的概念与同步相对,当一个进程或线程发起一个异步功能调用或者说提交任务方式是异步提交的时,不会立即得到结果。它会继续执行下一步代码。而异步功能完成后,通过状态、通知或回调函数来通知调用者。

如果是通过状态在通知,那么调用者需要每隔一段时间检查一次结果是否返回,效率很低。

如果使用通知或者回调的方式,则进程或线程就不需要再做额外的操作,效率很高。

阻塞 blocking

首先阻塞是一种状态,一种进程或者线程的状态,不要把阻塞与同步混淆。

也就是说当进程或线程发起调用或提交任务之后,结果返回之前,比如遇到IO操作,则调用者(该进程或线程)就会被挂起,然后只有等到有结果后才会再将阻塞的线程激活。

非阻塞 non-blocking

非阻塞与阻塞相反,就算不能立即得到结果也不会将其挂起,而是会继续执行下一步。

四种常见IO模型 

IO模型主要分五种

blocking IO    阻塞IO
    nonblocking IO  非阻塞IO
    IO multiplexing  复用型IO
    signal driven IO  信号驱动型IO
    asynchronous IO  异步IO

他们直接的区别点在于过程、进程(或线程)的状态、发起调用方式

首先最常见的IO模型:blocking IO

blocking IO

默认情况下,所有的socket都是阻塞IO,一个典型的read操作流程

non-blocking IO

设置socket可以使其变为非阻塞,当对一个非阻塞的socket执行读操作的时候,流程会不一样:

从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,
而是立刻返回一个error。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。
用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,
并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。
所以,用户进程其实是需要不断的主动询问kernel数据好了没有。

IO multiplexing

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

当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
这个图和blocking IO的图其实并没有太大的不同,事实上,还更差一些。因为这里需要使用两个system call (select 和 recvfrom),而blocking IO只调用了一个system call (recvfrom)。但是,用select的优势在于它可以同时处理多个connection。(多说一句。所以,如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。)
在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

Asynchronous I/O

用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。

小结

blocking和non-blocking的区别

调用blocking IO会一直block住对应的进程直到操作完成,而non-blocking IO在内核准备数据这个阶段,进程是不会非阻塞状态。

synchronous IO和asynchronous IO的区别

同步IO在进行IO操作的时候会将进程阻塞,而异步IO却不会。

所以blocking IO,non-blocking IO,IO multiplexing都属于synchronous IO,而asynchronous IO则不一样,当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。

最后各个IO Model的比较如图所示:

———————————————— 
版权声明:本文为CSDN博主「historyasamirror」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/historyasamirror/article/details/5778378

python并发编程之IO模型 同步 异步 阻塞 非阻塞的更多相关文章

  1. Python并发编程之IO模型

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) IO多路复用 异步IO IO模型比较分析 selectors模块 一.IO模型介绍 Stevens ...

  2. python并发编程之IO模型,

    了解新知识之前需要知道的一些知识 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调 ...

  3. python并发编程之IO模型(Day38)

    一.IO模型介绍 为了更好的学习IO模型,可以先看同步,异步,阻塞,非阻塞 http://www.cnblogs.com/linhaifeng/articles/7430066.html#_label ...

  4. 33 python 并发编程之IO模型

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

  5. 五 python并发编程之IO模型

    一 IO模型介绍 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问 ...

  6. python并发编程之IO模型(实践篇)

    一.阻塞IO 介绍略(请看概念篇) 二.非阻塞IO 在非阻塞式IO中,用户进程需要不断的主动询问kernel数据准备好了没有 # 服务端 import socket import time serve ...

  7. 第十篇.6、python并发编程之IO模型

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

  8. 第 13 章 python并发编程之io模型

    一.IO模型介绍 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问 ...

  9. 38、python并发编程之IO模型

    目录: 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 异步IO(Asynchron ...

随机推荐

  1. H5实现横向滚动的方法总结

    小程序中有横向滚动的swiper,H5中目前得手动实现. 实现方法如下: 外层需要设置: overflow: scroll;white-space: nowrap; 内层需要设置: display: ...

  2. haproxy 2.0 dataplaneapi docker 镜像

    为了方便测试dataplaneapi 基于官方的docker镜像,制作了一个简单的包含dataplaneapi 的镜像 下载dataplaneapi https://github.com/haprox ...

  3. Program terminated with signal 6, Aborted. (最后发现是数组越界导致)

    外网崩溃现象: 1.多台物理机中的多个进程消失,而且都是场景进程. 2.core文件都很小,看了 ulimit -a 和 cat proc/pid/limits  (都很正常.看这个是为了以后core ...

  4. 驱动中遍历模块,以及获取ntoskrnl.exe基址

    方法是基于PsLoadModuleList方式 驱动中遍历模块 一丶简介 简介: 进入内核了.遍历内核中使用的模块该怎么办. 其实在驱动中.我们的DriverEntry入口位置. 提供了两个参数. 一 ...

  5. 如果用了flex去加一个箭头怎么让他剧中

    左边是做了一个flex:1 右边是span的display:inline-block样式 父元素 .search-car-arrow display flex align-items center' ...

  6. .htaccess tricks总结

    目录 .htaccess tricks总结 一.什么是.htaccess 二.利用条件 三.利用方式 && tricks 1.将指定后缀名的文件当做php解析 2.php_value利 ...

  7. 第08组 Beta冲刺(3/4)

    队名 八组评分了吗 组长博客链接(2分) 组员1李昕晖(组长) 过去两天完成了哪些任务 文字/口头描述 了解各个小组的进度与难以攻破的地方,晚上安排开会,安排新的冲刺任务. 重新分配小组及个人任务. ...

  8. java判断指定路径文件夹是否存在,若不存在则创建新的文件夹

    File file = new File(dirPath); if (!file.exists()) { file.mkdirs(); }

  9. Web容器中DefaultServlet详解 JspServlet DefaultServlet

    Web容器中DefaultServlet详解 https://blog.csdn.net/qq_30920821/article/details/78328608 Web容器中DefaultServl ...

  10. Spring生态研习【五】:Springboot中bean的条件注入

    在springboot中,开发的确变的简单了很多,但是,开发者现在希望开发傻瓜式的方便搞定项目中的各种奇怪的需求最好了,不用烧脑,本来程序猿的生活就是枯燥的,不要再给自己添加更多的烦恼. 今天,就为了 ...