请求描述:

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

当进程调用一个进行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. DataGrid 的DataSource重新加载数据

    DataGrid 的DataSource重新加载数据,若直接重新给DataSource赋值是没有效果的,若只是修改原有数据中的单个值,此方法有效,但是针对完全不一样的数据直接重新赋值的方式是无效的,此 ...

  2. 在 window 上卸载 mysql

    1.停止 mysql 服务 开始——>控制面板——>管理工具——>服务,停掉 MySQL 的服务 2.卸载安装包 控制面板-添加删除程序,找到MySQL,卸载(可能会有多个安装包,需 ...

  3. c#数据筛选和排序

    一.TreeView SelectedNode    选中的节点            Level    节点的深度(从0开始)                AfterSelect    节点选中后 ...

  4. python3练习100题——018

    原题链接:http://www.runoob.com/python/python-exercise-example18.html 题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个 ...

  5. 关于真机测试root权限问题

    普通用户好像也无伤大雅: 输入后看到这样的有个美元符号,说明你的虚拟机获取不了权限,有权限的应该是root和#都有,这个时候你输入su 如果还是没有变化,看看你的虚拟机是不是android7.0,An ...

  6. c数据结构 -- 线性表之 顺序存储结构 于 链式存储结构 (单链表)

    线性表 定义:线性表是具有相同特性的数据元素的一个有限序列 类型: 1:顺序存储结构 定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构 算法: #include <stdio. ...

  7. 在Linux系统上安装Jenkins

    1.首先准备安装java环境,安装jdk 详情查看博客以,这里不做多介绍. 2.下载Jenkins至Linux服务器 查看内核版本信息:cat /proc/version uname -m cat / ...

  8. 工具使用:xmind

    概念 心智图,又称脑图.思维导图.灵感触发图.概念地图或思维地图,是一种图像式思维的工具与及一种利用图像式思考辅助工具来表达思维的工具. 详细的可以查看这里(维基百科)还有这里(百度百科) 用了思维导 ...

  9. crontab调用python脚本新思路

    crontab调用python脚本文件,有可能失败,定时执行并没有执行,怎么办? 答:写一个shell脚本调用python,然后用crontab调用shell脚本.具体细节,有时间补充. ————— ...

  10. 1059 Prime Factors (25分)

    1059 Prime Factors (25分) 1. 题目 2. 思路 先求解出int范围内的所有素数,把输入x分别对素数表中素数取余,判断是否为0,如果为0继续除该素数知道余数不是0,遍历到sqr ...