关于IO的同步,异步,阻塞,非阻塞

标签: 系统运维 | 发表时间:2011-08-04 04:53 | 作者:zava smile
出处:http://www.blogread.cn/it/

标签:  IO  非阻塞  同步  异步  阻塞

    上次写了一篇文章:Unix IO 模型学习。恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现。中途正好讨论了网络IO的同步、异步、阻塞、非阻塞的概念,当时讲下来,大家的理解各不相同,各执己见。搜索了网络上的一些文章,观点也各不相同,甚至连wiki也将异步和非阻塞当成一个概念在解释。

    虽然网络上充斥了大量关于同步、异步、阻塞、非阻塞的文章,但大都是抄来抄去,没有一个权威的说法。但我找到了这一篇文章,该文章引用了《UNIX网络编程 卷1》的介绍,这本书的作者是Richard Stevens。如果有Richard Stevens在这方面的定义或者结论,那么我想,这应该是比较有说服力的了。

    关于《UNIX网络编程 卷1》这本书,我特意找了英文原版,也共享出来了:大家可以下载《UNIX网络编程 卷1》的英文原版?HM格式)。

    我看了6.2这节内容,这节内容就是讲IO模型的。刚刚提到的那篇文章,几乎就是翻译这个6.2节的。应该说,这个6.2节,对同步和异步的讲解,算是很清楚的。

    下面是我自己理解的重点。

IO模型

    目前unix存在五种IO模型(这也和上一篇文章:Unix IO 模型 中提到的一致),分别是:

  • 阻塞型 IO(blocking I/O)
  • 非阻塞性IO(nonblocking I/O)
  • IO多路复用(I/O multiplexing)
  • 信号驱动IO(signal driven I/O)
  • 异步IO(asynchronous I/O)
  • IO的两个阶段

  • 等待数据准备好
  • 将数据从内核缓冲区复制到用户进程缓冲区
  • 同步,异步的区别

        那么究竟什么是同步和异步的区别呢?请重点读一下原文6.2节中的信号驱动IO和异步IO中的比较。最后总结出来是:

  • 同步IO,需要用户进程主动将存放在内核缓冲区中的数据拷贝到用户进程中。
  • 异步IO,内核会自动将数据从内核缓冲区拷贝到用户缓冲区,然后再通知用户。
  •     这样,同步和异步的概念就非常明显了。以上的五种IO模型,前面四种都是同步的,只有第五种IO模型才是异步的IO。

    阻塞和非阻塞

        那么阻塞和非阻塞呢?注意到以上五个模型。阻塞IO,非阻塞IO,只是上面的五个模型中的两个。阻塞,非阻塞,是针对单个进程而言的。

        当对多路复用IO进行调用时,比如使用poll。需注意的是,poll是系统调用,当调用poll的时候,其实已经是陷入了内核,是内核线程在跑了。因此对于调用poll的用户进程来讲,此时是阻塞的。

        因为poll的底层实现,是去扫描每个文件描述符(fd),而如果要对感兴趣的fd进行扫描,那么只能将每个描述符设置成非阻塞的形式(对于用户进程来讲,设置fd是阻塞还是非阻塞,可以使用系统调用fcntl),这样才有可能进行扫描。如果扫描当中,发现有可读(如果可读是用户感兴趣的)的fd,那么select就在用户进程层面就会返回,并且告知用户进程哪些fd是可读的。

        这时候,用户进程仍然需要使用read的系统调用,将fd的数据,从内核缓冲区拷贝到用户进程缓冲区(这也是poll为同步IO的原因)。

        那么此时的read是阻塞还是非阻塞呢?这就要看fd的状态了,如果fd被设置成了非阻塞,那么此时的read就是非阻塞的;如果fd被设置成了阻塞,那么此时的read就是阻塞的。

        不过程序已经执行到了这时候,不管fd是阻塞还是非阻塞,都没有任何区别,因为之前的poll,就是知道有数据准备好了才返回的,也就是说内核缓冲区已经有了数据,此时进行read,是肯定能够将数据拷贝到用户进程缓冲区的。

        但如果换种想法,如果poll是因为超时返回的,而我们又对一个fd(此fd是被poll轮询过的)进行read调用,那么此时是阻塞还是非阻塞,就非常有意义了,对吧!

    结论

  • 判断IO是同步还是异步,是看谁主动将数据拷贝到用户进程。
  • select或者poll,epoll,是同步调用,进行此调用的用户进程也处于阻塞状态。
  • javaScript或者nodejs中的读取网络(文件)数据,然后提供回调函数进行处理,是异步IO。
  • 您可能还对下面的文章感兴趣:

    1. MySQL在切换binlog时会阻塞更新 [2009-10-28 22:47:20]


    相关 [io 同步 异步] 推荐:

    关于IO的同步,异步,阻塞,非阻塞

    - smile - IT技术博客大学习
    标签:  IO  非阻塞  同步  异步  阻塞.     上次写了一篇文章:Unix IO 模型学习. 恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现. 中途正好讨论了网络IO的同步、异步、阻塞、非阻塞的概念,当时讲下来,大家的理解各不相同,各执己见.

    linux异步IO浅析

    - Sepher - kouu's home
    知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个CPU密集型的应用中,有一些需要处理的数据可能放在磁盘上. 预先知道这些数据的位置,所以预先发起异步IO读请求. 等到真正需要用到这些数据的时候,再等待异步IO完成. 使用了异步IO,在发起IO请求到实际使用数据这段时间内,程序还可以继续做其他事情).

    异步IO一定更好吗?

    - Wolf - CNode社区
    在长林的文章《nodejs异步IO的实现》中提到,NodeJS通过libeio来实现IO操作的异步化,而libeio采用多线程的方式来模拟异步操作. 这里我需要强调一个观点,异步IO虽然是NodeJS一个非常重要的特点,但异步IO并不总是最好的,其他语言也一样. 在我的磁盘上有2个文件,我希望在一个程序里读取这2个文件,每次输出一个字符.

    linux AIO (异步IO) 那点事儿

    - zffl - CNode社区
    这时候进程至少会阻塞10次,而这可能会导致其他的上千个用户请求得不到处理,这当然是不能接受的.. Linux AIO 早就被提上议程,目前比较知名的有 Glibc 的 AIO   与 Kernel Native AIO. 我们用Glibc 的AIO 做个小实验,写一个简单的程序:异步方式读取一个文件,并注册异步回调函数:.

    物理IO与逻辑IO

    - - 操作系统 - ITeye博客
    IO性能对于一个系统的影响是至关重要的. 一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到IO. 而IO性能的发展,明显落后于CPU的发展. Memchached也好,NoSql也好,这些流行技术的背后都在直接或者间接地回避IO瓶颈,从而提高系统性能. 上图层次比较多,但总的就是三部分.

    从同步到异步,从匿名到实名

    - keso - 乱象,印迹
    题记:完成正则表达式的书稿,对许多事情不再麻木,慢慢恢复写点东西的意识. 虽然对网络没太多钻研,但从97年至今,自己上网的历史也有十多年了. 在我眼里,这些年来网络呈现出两个趋势:从同步到异步,从匿名到实名,所以写了这篇散记. 先说从同步到异步(这里借用了计算机专业中的两个术语,有必要为不熟悉的读者做一点解释:异步是一种松散的通讯模式,一方发送消息之后,不需要等待对方回复,即可以接续处理,电子邮件就是最常见的异步通讯模式;同步则是较为紧密的通讯模式,一方发送消息之后,需要等到对方回复,才可以接续处理).

    12c ADG的同步和异步灾备方案

    - -
    这样既可以保证零数据丢失又可以降低主库压力. Far Sync实例只有密码文件,init参数文件和控制文件,而没有数据文件. 如果redo 传输采用Maximum Availability模式,我们可以在距离生产中心(Primary Database)相对较近的地点配置Far Sync实例,主库(Primary Database)同步(synchronous)传输redo到Far Sync实例,保证零数据丢失(zero data loss),同时主库和Far Sync距离较近,网络延时很小,因此对主库性能影响很小.

    java nio和io的比较

    - - 互联网 - ITeye博客
    第一部分:简单介绍NIO.     服务器在合理时间内处理大量客户机的请求的能力取决于服务器使用I/O流的效率,同时为成百上千的客户提供服务的服务器必须能并发的使用I/O服务.     用Java语言写的服务器,由于其线程与客户机之比几乎是一比一,因而易受到大量线程开销的影响,其结果是即导致性能问题,又缺乏伸缩性.

    js文件引用方式及其同步执行与异步执行

    - - JavaScript - Web前端 - ITeye博客
    任何以appendChild(scriptNode) 的方式引入的js文件都是异步执行的 (scriptNode 需要插入document中,只创建节点和设置 src 是不会加载 js 文件的,这跟 img 的与加载不同 )   . html文件中的