请求描述:

`阻塞/非阻塞` 和 `同步/异步` 不是一个概念。举几个简单的例子。

当进程调用一个进行IO操作的API时(比如read函数),在数据没有到达前,read 会挂起,进程会卡住。在数据读取完毕返回给进程时,

      read 返回(返回值为读取到的字节数,数据从内核拷贝到用户空间),然后进程继续执行。那么这次 read 调用,是阻塞的。

非阻塞就是 read 在数据没有读取完毕前,就返回了(返回值为-1,errno 设置为 EAGAIN)。此时进程没有拿到需要的数据。那怎么办?

 
 
有两种办法。

一种是同步

因为进程没办法知道数据什么时候才真正读取完毕了,所以需要每隔一段时间就去轮询一下(就是重新调用 read,看是不是数据真的已经读取完毕了)。

   大部分场景中都不会使用这种方式。但在某些特殊的情况下效率会特别高。

一种是异步:

早期的异步实现方式是内核给进程发信号(SIGIO 或者 SIGPOLL)。数据读写完毕后,内核发信号给进程,然后进程内的信号处理函数再调用 read 读取数据(这时可以确保数据真的已经读取完毕了)。但这种方式有一个小小的瑕疵,就是在进程进行多个 fd 读写的时候,信号来的时候没办法分清到底是哪个 fd 上的数据已经真正准备好了。所以进程还是要对所有持有的 fd 进行 read 调用。
    后来的异步实现,就有了更好的 select / poll / epoll(I/O multiplexing)。现在基本上像比较流行的 Nginx / Redis 都用 epoll(在 FreeBSD 上是 kqueue)

 
 
 

图解:

阻塞式I/O模型:默认情况下,所有套接字都是阻塞的。怎么理解?先理解这么个流程,一个输入操作通常包括两个不同阶段:

(1)等待数据准备好;
(2)从内核向进程复制数据。

对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所有等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用程序缓冲区。 好,下面我们以阻塞套接字的recvfrom的的调用图来说明阻塞

标红的这部分过程就是阻塞,直到阻塞结束recvfrom才能返回。

非阻塞式I/O: 以下这句话很重要:进程把一个套接字设置成非阻塞是在通知内核,当所请求的I/O操作非得把本进程投入睡眠才能完成时,

不要把进程投入睡眠,而是返回一个错误。看看非阻塞的套接字的recvfrom操作如何进行

可以看出recvfrom总是立即返回。

I/O多路复用:虽然I/O多路复用的函数也是阻塞的,但是其与以上两种还是有不同的,I/O多路复用是阻塞在select,epoll这样的系统调用之上,

而没有阻塞在真正的I/O系统调用如recvfrom之上。如图

信号驱动式I/O:用的很少,就不做讲解了。直接上图

异步I/O:这类函数的工作机制是告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到用户空间)完成后通知我们。如图:

注意红线标记处说明在调用时就可以立马返回,等函数操作完成会通知我们

例子说明:

 例子一:
       一个网络包从应用程序A发到另一台电脑上的应用程序B,需要经历:
  1. 从A的业务代码到A的软件框架
  2. 从A的软件框架到计算机的操作系统内核
  3. 从A所在计算机的内核到网卡
  4. 从网卡经过网线发到交换机等设备,层层转发,到达B所在计算机的网卡
  5. 从B所在计算机的网卡到B所在计算机的内核
  6. 从B所在计算机的内核到B的程序的用户空间
  7. 从B的软件框架到B的业务代码

例子二:

小乐爱喝茶,废话不说,煮开水。
    出场人物:小乐,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
       1 小乐把水壶放到火上,立等水开。(同步阻塞)
         ——   小乐觉得自己有点傻
       2 小乐把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
         ——  小乐还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出呜呜~~~~的噪音。
       3 小乐把响水壶放到火上,立等水开。(异步阻塞)
         ——  小乐觉得这样傻等意义不大
       4 小乐把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
         ——  小乐觉得自己聪明了。

所谓同步异步,只是对于水壶而言。
     普通水壶,同步;响水壶,异步。
     虽然都能干活,但响水壶可以在自己完工之后,提示小乐水开了。这是普通水壶所不能及的。
     同步只能让调用者去轮询自己(情况2中),造成小乐效率的低下。

所谓阻塞非阻塞,仅仅对于小乐而言。
    —— 立等的小乐,阻塞;看电视的小乐,非阻塞。

情况1和情况3中小乐就是阻塞的,媳妇喊他都不知道。

虽然3中响水壶是异步的,可对于立等的小乐没有太大的意义。

所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。

阻塞式I/0 和 非阻塞式I/O 同步异步详细介绍的更多相关文章

  1. Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]【转】

    转自:http://blog.csdn.net/jacobywu/article/details/7475432 阻塞型I/O和非阻塞I/O 阻塞:休眠 非阻塞:异步通知 一 休眠 安全地进入休眠的两 ...

  2. 五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O

    五种I/O 模式——阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/O 五种I/O 模式:[1]        阻塞 I/O          ...

  3. Linux非阻塞IO(四)非阻塞IO中connect的实现

    我们为客户端的编写再做一些工作. 这次我们使用非阻塞IO实现connect函数. int connect(int sockfd, const struct sockaddr *addr, sockle ...

  4. Linux非阻塞IO(三)非阻塞IO中缓冲区Buffer的实现

    本文我们来实现回射服务器的Buffer.   Buffer的实现   上节提到了非阻塞IO必须具备Buffer.再次将Buffer的设计描述一下: 这里必须补充一点,writeIndex指向空闲空间的 ...

  5. JAVA阻塞(IO)和非阻塞(NIO)

    查看这篇文章,了解更多关于Java的阻塞和非阻塞替代创建套接字的信息. 套接字使用TCP / IP传输协议,是两台主机之间的最后一块网络通信. 您通常不必处理它们,因为它们之上构建了协议,如HTTP或 ...

  6. Java基础——NIO(二)非阻塞式网络通信与NIO2新增类库

    一.NIO非阻塞式网络通信 1.阻塞与非阻塞的概念  传统的 IO 流都是阻塞式的.也就是说,当一个线程调用 read() 或 write() 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在 ...

  7. Linux NIO 系列(03) 非阻塞式 IO

    目录 一.非阻塞式 IO 附:非阻塞式 IO 编程 Linux NIO 系列(03) 非阻塞式 IO Netty 系列目录(https://www.cnblogs.com/binarylei/p/10 ...

  8. 阻塞式和非阻塞式IO

    有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...

  9. NIO非阻塞式编程

    /** * NIO非阻塞式编程<p> * 服务端和客户端各自维护一个管理通道的对象,我们称之为selector,该对象能检测一个或多个通道 (channel) 上的事件. * 我们以服务端 ...

随机推荐

  1. nginx 部署php项目 404

    服务器重启了一下 然后访问程序报错404的情况 文件存在位置没有问题 niginx配置根目录没有问题 最后检查到端口的时候发现php-fpm的9000端口未打开 service php-fpm res ...

  2. TD - 输入框

    模板1:TD - 普通输入框 <input dojoType="bootstrap.form.ValidationTextBox" dojoAttachPoint=" ...

  3. Java基础--数组(Arrays)

    数组(Array),是多个相同类型数据按一定顺序排列 的集合,并使用一个名字命名,并通过编号的方式 对这些数据进行统一管理.本篇博客是对Java基础中的数组进行详细说明. 目录: 数组的概述 一维数组 ...

  4. vscode里的NPM脚本

    NPM脚本的开启与关闭 点击设置-功能-任务 控制为所有任务提供程序扩展启用"提供任务".如果"任务:运行任务"命令速度较慢,则禁用任务提供程序的自动检测可能会 ...

  5. 一文带你看清HTTP所有概念(转)

    一文带你看清HTTP所有概念   上一篇文章我们大致讲解了一下 HTTP 的基本特征和使用,大家反响很不错,那么本篇文章我们就来深究一下 HTTP 的特性.我们接着上篇文章没有说完的 HTTP 标头继 ...

  6. JavaScript的Map和Set

    JavaScript的Map和Set 1.map:映射(通过key获得value).增.删 2.set:增.删.判断是否包含某个元素 1. Map <!DOCTYPE html><h ...

  7. 虚拟机win7 安装过程中遇到虚拟工具安装失败

    如果遇见这样的问题 倘若你用的是这样的镜像:cn_windows_7_enterprise_x64_dvd_x15-70741.iso 换镜像源.换镜像源.换镜像源! 换成带sp1的iso镜像:cn_ ...

  8. g++运行c++程序提示main()找不到

    /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x20) ...

  9. 读书笔记 (.NET企业级应用架构设计)

    建议你自己和别人多沟通(学会沟通会使你在公司更好的发展,有意见就提,有问题就问,有困难就说)加油lxp 1.架构师是用来干嘛的: 架构师分析需求,分析系统要去做什么,架构怎么去做 2.架构师的职责是: ...

  10. Centos7部署jenkins

    1.       下载rpm包: a)         下载地址:https://pkg.jenkins.io/redhat-stable/ b)         点选一个下载即可,例如点选:“jen ...