阻塞IO与非阻塞IO、同步IO与异步IO
在学习nodejs时,了解到nodejs的一个重要特征是非阻塞IO,且nodejs中的所有IO都是异步的。既然有非阻塞IO、异步IO,那么必然就有阻塞IO、同步IO了,为了彻底搞清楚这几个概念,在网上找了几个博客进行了参考,现整理如下。
在了解这几个词语之前,需要了解几个概念:
- 用户空间与内核空间
- IO操作的基本流程
- IO模型
一、用户空间与内核空间
每一台计算机都有一个或者多个操作系统,而操作的的核心就是内核。内核其实可以看成是最重要的应用程序,所以它会有自己相应的内存空间,这个内存空间就是内核空间。内核可以访问底层硬件设备的所有权限。为了保护内核不被普通的应用程序直接操作,从而将内存空间划分为内核空间和用户空间,普通的应用程序就是运行在用户空间。
二、IO操作的基本流程
当应用程序调用类似read等函数读取数据的时候,此时会执行一个系统调用,也就是调用内核的函数去读取响应的数据文件。首先内核会将对应的数据读取到内核空间,等数据都读取完毕之后,内核通知用户程序读取内核空间的数据,将其复制到对应的用户空间,此时才算完成一次数据的读取操作。
这个过程涉及到两个步骤
1、内核将数据读取到内核空间
2、内核通知应用程序将对应的数据从内核空间拷贝到用户空间
三、IO模型
这里统一使用Linux下的系统调用recv作为例子,它用于从套接字上接收一个消息,因为是一个系统调用,所以调用时会从用户进程空间切换到内核空间运行一段时间再切换回来。默认情况下recv会等到网络数据到达并且复制到用户进程空间或者发生错误时返回,而第4个参数flags可以让它马上返回。
- 阻塞IO模型
使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。
A同学用杯子装水,打开水龙头装满水然后离开。这一过程就可以看成是使用了阻塞IO模型,因为如果水龙头没有水,他也要等到有水并装满杯子才能离开去做别的事情。很显然,这种IO模型是同步的。
我要水,一直等待,直到有水了,装满再走,装水的过程一直需要等待。完全阻塞同步IO型。
- 非阻塞IO模型
改变flags,让recv不管有没有获取到数据都返回,如果没有数据那么过一段时间后再调用recv看看,如此循环。
B同学也用杯子装水,打开水龙头后发现没有水,它离开了,过一会他又拿着杯子来看看……在中间离开的这些时间里,B同学离开了装水现场(回到用户进程空间),可以做他自己的事情。这就是非阻塞IO模型。但是它只有是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间(等着水将水杯装满),因此它还是同步IO。
我要水,可以先干点别的,但是不断地查看水龙头是否来水了,而且,因为多个人都是这种状态,肯定有先后顺序(优先级),所以他是非阻塞的同步IO性。
- IO复用模型
这里在调用recv前先调用select或者poll,这2个系统调用都可以在内核准备好数据(网络数据到达内核)时告知用户进程,这个时候再调用recv一定是有数据的。因此这一过程中它是阻塞于select或poll,而没有阻塞于recv,有人将非阻塞IO定义成在读写操作时没有阻塞于系统调用的IO操作(不包括数据从内核复制到用户空间时的阻塞,因为这相对于网络IO来说确实很短暂),如果按这样理解,这种IO模型也能称之为非阻塞IO模型,但是按POSIX来看,它也是同步IO,那么也和楼上一样称之为同步非阻塞IO吧。
这种IO模型比较特别,分个段。因为它能同时监听多个文件描述符(fd)。
这个时候C同学来装水,发现有一排水龙头,舍管阿姨告诉他这些水龙头都还没有水,等有水了告诉他。于是等啊等(select调用中),过了一会阿姨告诉他有水了,但不知道是哪个水龙头有水,自己看吧。于是C同学一个个打开,往杯子里装水(recv)。这里再顺便说说鼎鼎大名的epoll(高性能的代名词啊),epoll也属于IO复用模型,主要区别在于舍管阿姨会告诉C同学哪几个水龙头有水了,不需要一个个打开看(当然还有其它区别)。
我要水,可以先干别的事情,但是无需自己查看水龙头是否来水了,有专人告知直接去哪个水龙头装水,比上面一种需要自己查看水龙头是否来水了效率更高。因为接水的过程还是要自己去做,所以也是同步IO,属于高效率版的同步IO型。
- 信号驱动IO模型
通过调用sigaction注册信号函数,等内核数据准备好的时候系统中断当前程序,执行信号函数(在这里面调用recv)。
D同学让舍管阿姨等有水的时候通知他(注册信号函数),没多久D同学得知有水了,跑去装水。是不是很像异步IO?很遗憾,它还是同步IO(省不了装水的时间啊)。
和上面情况类似,只是通过信号机制实现,属于高效率版的同步IO型。
- 异步IO模型
调用aio_read,让内核等数据准备好,并且复制到用户进程空间后执行事先指定好的函数。
E同学让舍管阿姨将杯子装满水后通知他。整个过程E同学都可以做别的事情(没有recv),无需等待装水的时间(也就是读写操作无阻塞)这才是真正的异步IO。
我需要水,同时我可以去干别的事情,专人给我装好水了通知我过来拿。相当于综合了上面的情况:1、你给我准备好东西,我去干点别的;2、准备好了通知我来拿东西。一刻也不耽误,这种属于无阻塞异步IO型。
最后,总结比较下五种IO模型:
IO分两阶段:
1.数据准备阶段
2.内核空间复制回用户进程缓冲区阶段
一般来讲:阻塞IO模型、非阻塞IO模型、IO复用模型(select/poll/epoll)、信号驱动IO模型都属于同步IO,因为阶段2是阻塞的,还是需要自己花时间去干(尽管时间很短)。只有异步IO模型是符合POSIX异步IO操作含义的,不管在阶段1还是阶段2都可以干别的事。
- ps:以上图片均截自UNIX网络编程卷1。
阻塞io是对于线程而言,则是在进行数据的读取操作的时候,此时线程会主动执行阻塞操作,直到内核完成对数据的读取。(老老实实排队等待,轮到自己后,自己干活)
而同步io则是指在内核读取数据完毕之后,需要应用程序主动将数据从内核空间拷贝到用户空间,此时这个阶段线程是阻塞的。
而对于异步io而言,不需要主动拷贝数据,都是内核完成之后通知应用程序。(无需排队,我先去干别的,我要的东西给我准备好了通知我,直接过来拿东西)
nodejs属于非阻塞IO型,可以先去干别的事情,将需要等待的操作放入循环事件中,一旦需要等待的操作完成后,通过callback传回给应用。
阻塞IO与非阻塞IO、同步IO与异步IO的更多相关文章
- 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...
- 转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
此文章为转载,如有侵权,请联系本人.转载出处,http://blog.chinaunix.net/uid-28458801-id-4464639.html 同步(synchronous) IO和异步( ...
- 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- 同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- 深入理解非阻塞同步IO和非阻塞异步IO
这两篇文章分析了Linux下的5种IO模型 http://blog.csdn.net/historyasamirror/article/details/5778378 http://blog.csdn ...
- python网络编程-同步IO和异步IO,阻塞IO和非阻塞IO
同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network IO. ...
- 阻塞IO、非阻塞IO、同步IO、异步IO等
https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...
- 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO
POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...
- 阻塞式和非阻塞式IO
有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...
- 理论铺垫:阻塞IO、非阻塞IO、IO多路复用/事件驱动IO(单线程高并发原理)、异步IO
完全来自:http://www.cnblogs.com/alex3714/articles/5876749.html 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同 ...
随机推荐
- 在python当中使用redis
redis数据库 # 1.安装redis与可视化操作工具 # 2.在服务中管理redis服务器的开启关闭 # 3.命令行简单使用redis: -- redis-cli # 启动客户端 -- set k ...
- spark源码阅读--shuffle读过程源码分析
shuffle读过程源码分析 上一篇中,我们分析了shuffle在map阶段的写过程.简单回顾一下,主要是将ShuffleMapTask计算的结果数据在内存中按照分区和key进行排序,过程中由于内存限 ...
- vue前端实战注意事项
1. vue前端实战注意事项 1.1. 预备 1.1.1. Eslint 这是个语法检查工具,我用webstorm作为开发的ide,这个语法检查还是太严格了,一个空格啥的都会报错,对新手来讲还是建议关 ...
- Vue学习之品牌案例部分代码小结(二)
品牌案例的增删查和其他部分效果: <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- 22、vue实现随机四位数验证码
效果图: 1.新建生成验证码的组件Sidentify.vue(代码如下): <template> <div class="s-canvas"> <ca ...
- 4 Android可执行文件
APK是Android Package缩写,使用zip解压文件即可打开.每个APK文件中都包含一个class.dex文件(odex过的APK文件除外).class.dex文件就是Android系统Da ...
- AES加密解密工具类封装(AESUtil)
package club.codeapes.common.utils; import org.springframework.util.Base64Utils; import javax.crypto ...
- MongoDB(NoSQL) 非关系型数据库
目录 简单了解 mongoDB 简单使用mongoDB 简单了解 mongoDB # NoSQL 泛指非关系型的数据库 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅 ...
- pecl安装php扩展
Pecl全称The PHP Extension Community Library,php社区扩展库,由社区编写,维护. 使用pecl方便之处在于我们不用到处找源码包下载编译,配置,不用手动phpiz ...
- Linux运维技术之NFS网络文件系统
NFS:网络文件系统,只能工作在Unix/linux之间,不能与windows之间交互. NFS文件系系统只能基于ip来认证! RPC:远程过程调用,简化分布式应用程序的开发, 对Linux系统而言, ...