来源:http://shmilyaw-hotmail-com.iteye.com/blog/1896683

概括来说,一个IO操作可以分为两个部分:发出请求、结果完成。如果从发出请求到结果返回,一直Block,那就是Blocking IO(常见的顺序化程序结构);如果发出请求就可以返回(结果完成不考虑),就是non-blocking
IO;如果发出请求就返回,结果返回是Block在select或者poll上的,则其只能称为IO multiplexing;如果发出请求就返回,结果返回通过Call Back的方式被处理,就是AIO。

文[2]中图画的不错,说的也比较清楚借来用一下。

Blocking IO

先从这个开始讨论起,在前面的文章里,我们知道一个server端的程序要和一个客户端通信,它首先自己要绑定到一个端口,然后调用accept方法来接收一个客户端的请求并建立连接。这个accept返回的socket连接可以获取到双方通信的InputStream和OutputStream,这样双方就可以通过这两个Stream来互相发消息了。

当然,对于单独的一个server进程和一个client进程来说,这是一个典型的场景。但是如果对于有多个client的情况下,我们该怎么来处理呢?一种典型的思路就是,我们针对每一个client连接请求建立一个thread来处理。这种模式如下图:

按照这种思路,针对每一个client,我们都有一个对应的handler来处理他们的业务逻辑。每个handler对应一个线程。

我们再想想,在有大量用户连接的情况下,server将针对所有连接client创建thread。如果有成千上万的连接的话,这将是一个很大的开销。由于系统资源实际的限制,可能会占用大量的资源甚至会导致资源被消耗光的情况。另外,这么多个线程连接需要处理,CPU需要在多个线程之间切换。在大量线程的情况下,切换的开销也很大。在这些情况下,请求量大的时候系统的性能和资源利用率都不高。那么我们有没有什么办法可以提高资源利用率和性能呢?

Non-Blocking IO

除了前面提到的blocking IO,其实还有一种io的方式,就是Non-Blocking IO。在详细讨论Non-Blocking IO之前,我们先看看原来blocking IO的一些不足。我们前面的每个连接一个线程的方式如下图所示:

对于每一个连接的所有操作,从建立连接,准备数据,读取数据,编码,解码以及来回发送数据,都在一个线程里全包了。之所以会出现前面提到的资源利用率不高和系统性能受到影响,就是因为通过socket进行io的系统性能和系统本身进程性能本身是有大的差异的。一般来说,IO的性能比系统CPU的性能要差几个数量级。所以才会有大量线程要处理数据的时候,都卡在这里等IO了。这就是前面这种方式有问题的根源所在了。

那么,我们有没有什么办法可以改进一下呢?我们这个时候可以考虑一下异步程序执行的思路。一般对于异步程序执行来说,在调用某一个方法的时候,这个被调用的方法在另外的一个进程或者线程中执行。这个调用方法的进程并不等被调用的方法返回结果,而是继续执行自己后面的过程。可是,在调用的目标方法结束之后,我们怎么让这个调用方法的进程知道方法执行结束了并知道方法的结果呢?这个时候,我们很多时候会使用一种回调的机制。关于回调机制的思路,和我前面一篇讨论Observer模式的文章说的非常近似。笼统的来说,就是我这个调用方法的进程实现注册好了一个通知的机制,然后在被调用方法结束后,这个被调用的方法进程通过这个机制来通知我。

如果我们借鉴这个思路,比如说前面有一些客户端连接服务器端,它们只需要把要操作的目的资源,比如写某个文件之类的,针对哪个socket等等关联起来。等一旦socket连接准备好了再触发它们。这样就不需要开这么多个线程来等了。这些socket连接ready等行为相当于一个定义的一个事件被触发了。我们很多要被回调的方法都放在一个事件通知的队列里。这些回调事件的执行可以放到单独的一个线程里执行。这样也就不需要前面那么多的线程,也减少了线程间切换的开销。

Blocking IO

这个最好理解了,在Blocking IO模式下,函数调用只有在操作完成后才会返回。下图是它调用过程的图示:

重点解释下上图,下面例子都会讲到。首先application调用 recvfrom()转入kernel,注意kernel有2个过程,wait for data和copy data from kernel to user。直到最后copy complete后,recvfrom()才返回。此过程一直是阻塞的。

Non-Blocking IO

Non-Blocking 是Blocking的反,也就是说,即使操作没有完成,函数也可以返回。调用过程如下:

可以看见,如果直接操作它,那就是个轮询。。直到内核缓冲区有数据


AIO也是这样啊?对!这是Non-Blocking IO 和AIO的共同点。其实从概念层面来说Non-Blocking IO 就是AIO,他们没有什么区别。但是Non-Blocking IO是对文件描述符(*nix)或者Handle(Windows)的设置,在执行操作时不需要特殊的数据结构。Non-Blocking
IO提交请求后只能通过提交的操作函数来查询操作是否完成,这是一个很大的限制。而AIO往往会提供多种通知或者查询机制,也就是说用Non-Blocking IO时只能轮询,而AIO有更多选择(其它通知机制)。所以是否支持轮询外的其他机制是AIO和Non-Blocking
IO的区别。

I/O multiplexing (select and poll)

最常见的I/O复用模型,select。

select先阻塞,有活动套接字才返回。与blocking I/O相比,select会有两次系统调用,但是select能处理多个套接字。

关于Blocking IO,non-Blokcing IO,async IO的区别和理解的更多相关文章

  1. Async IO

    I was recently reading a series on “Write Sequential Non-Blocking IO Code With Fibers in NodeJS” by  ...

  2. 一款DMA性能优化记录:异步传输和指定实时信号做async IO

    关键词:DMA.sync.async.SIGIO.F_SETSIG. DMA本身用于减轻CPU负担,进行CPU off-load搬运工作. 在DMA驱动内部实现有同步和异步模式,异步模式使用dma_a ...

  3. [Functional Programming] Async IO Functor

    We will see a peculiar example of a pure function. This function contained a side-effect, but we dub ...

  4. System.IO.Pipelines: .NET上高性能IO

    System.IO.Pipelines是一个新的库,旨在简化在.NET中执行高性能IO的过程.它是一个依赖.NET Standard的库,适用于所有.NET实现. Pipelines诞生于.NET C ...

  5. 《Linux/UNIX系统编程手册》第63章 IO多路复用、信号驱动IO以及epoll

    关键词:fasync_helper.kill_async.sigsuspend.sigaction.fcntl.F_SETOWN_EX.F_SETSIG.select().poll().poll_wa ...

  6. 同步IO与同步非阻塞IO的理解

    本文图片均来自网络 一.同步IO---Blocking IO 在Blocking IO模型中,用户空间的应用程序执行一个系统调用(recvform),这会导致应用程序阻塞,直到数据准备好,并且将数据从 ...

  7. IO模型《六》IO模型比较分析

    IO模型比较分析 到目前为止,已经将四个IO Model都介绍完了.现在回过头来回答最初的那几个问题:blocking和non-blocking的区别在哪,synchronous IO和asynchr ...

  8. IO模型《一》IO模型介绍

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

  9. IO - 同步 异步 阻塞 非阻塞的区别,学习Swoole有帮助

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?本文较长需耐心阅读,基础 ...

随机推荐

  1. 洛谷1525 关押罪犯NOIP2010 并查集

    问题描述 S城现有两座监狱,一共关押着N名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两 ...

  2. 由防止表单重复提交引发的一系列问题--servletRequest的复制、body值的获取

    @Time:2019年1月4日 16:19:19 @Author:QGuo   背景:最开始打算写个防止表单重复提交的拦截器:网上见到一种不错的方式,比较合适前后端分离,校验在后台实现: 我在此基础上 ...

  3. 监控memcached服务

    #!/bin/bash #监控memcached服务 printf "del key\r\n" | nc 127.0.0.1 11211 &>/dev/null #使 ...

  4. 【转】 基于C#.NET的高端智能化网络爬虫 2

    [转] 基于C#.NET的高端智能化网络爬虫2 本篇故事的起因是携程旅游网的一位技术经理,豪言壮举的扬言要通过他的超高智商,完美碾压爬虫开发人员,作为一个业余的爬虫开发爱好者,这样的言论我当然不能置之 ...

  5. HDU 5386 Cover(模拟)

    Cover Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Subm ...

  6. _DataStructure_C_Impl:Dijkstra算法求最短路径

    // _DataStructure_C_Impl:Dijkstra #include<stdio.h> #include<stdlib.h> #include<strin ...

  7. JS控制光标定位,定位到文本的某个位置

    这是一个数字密码,要能够智能的跳转到文本的某个位置,就需要通过JS来控制跳转! 1.onkeyup监听 <input class="put" id="number- ...

  8. MySQL Server 5.5.44免安装版配置详解

    转载地址:http://wenku.baidu.com/view/2a8bfe6a25c52cc58bd6beff.html### 一 下载MySQL http://dev.mysql.com/dow ...

  9. C# Cache的类方法

    public class DataCache    {        /// <summary>        /// 获取当前应用程序指定CacheKey的Cache值        / ...

  10. css3 背景过度实现

    代码: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&q ...