[翻译]各个类型的IO - 阻塞, 非阻塞,多路复用和异步
同事推荐,感觉写的不错就试着翻译了下.
原文链接: https://www.rubberducking.com/2018/05/the-various-kinds-of-io-blocking-non.html
作者: Didier A.
我发现对于软件程序员来说很难分清楚各种类型的IO.对于阻塞,非阻塞,多路复用和异步IO有很多的混淆点.
所以我想尝试解释清楚各种IO类型意味着什么
在硬件层面.
在现代操作系统中,IO(输入/输出)是一种和外围设备交换数据的方式.包括读写磁盘或SSD,通过网络发送和接受数据,在显示器上显示,接入键盘和鼠标输入,等等.
现代操作系统和外围设备的交流取决于外围设备的特定类型以及他们的固件版本和硬件能力.
通常来说,你可以认为外围设备是很高级的,他们可以同时处理多个并发的读写数据请求.也就是说,串行交流的日子一去不返了.
在这些场景中,外围设备和CPU间的交流在硬件层面都是异步的.
这个异步机制被称为硬件中断.
想想一个简单的场景,CPU请求外围设备去读取一些数据,接着CPU会进入一个无限循环,每一次都会检查外围设备的数据是否可用,直到获得了数据为止.
这种方法被称为轮询(polling
),因为CPU需要保持检查外围设备.
在现代硬件中,取而代之发生的是CPU请求外围硬件执行操作,然后就忘了这件事,继续处理其他的CPU指令.只要外围设备做完了,他会通过电路中断来通知CPU.
这发生在硬件中,CPU因此不需要停下来或者检查这个外围设备,可以继续执行其他的工作,直到周边设备说已经做完了.
在软件层面
现在我们了解了硬件中发生的事,我们可以移动到软件这一侧了.
在这一层IO通过多种方式被暴露:阻塞,非阻塞,多路复用和异步.让我们一个个来仔细解释.
阻塞
还记得用户程序如何在一个进程内运行,代码是在线程的上下文中执行的吗?
你总是会遇到需要编写一个需要从文件中读取数据的程序的情况.
使用阻塞IO,你所做的是从你的线程中请求操作系统,将线程置于休眠(sleep),当数据可用于被消费时操作系统会唤醒线程.
也就是说,阻塞IO之所以被称为阻塞是因为使用他的线程会被阻塞直到IO完成.
非阻塞
阻塞IO的问题是当你的线程在休眠时,他除了等IO完成不能干其他事.
有时候,你的程序可能没有其他事可做了.
但如果还有其他事需要做的话,能在等待IO的时候并发做可是极好的.
其中一种实现方式被称为非阻塞IO.
他的思想是当你读取一个文件时,OS只是简单返回给你文件的内容或者一个等待状态告诉你IO还未完成,而不是将线程休眠.
他不会阻塞你的线程,但之后检查IO是否完成的工作还是交给了你.
这意味着当处于等待状态时,你可以去做一些工作,当你再次需要IO时,可以再读取一次,那时候IO可能已经完成了,文件的内容会返回,如果还是处于等待状态的话,你可以选择继续做其他事.
多路复用
非阻塞IO的问题是如果你在等待IO的过程中要做的其他事情就是另外的IO的话,事情会变得很奇怪.
在一个好的场景下,你请求OS去读取文件A的内容,然后去做一些重计算的工作,做完之后再去检查文件A是否完成读取,如果完成了,你再做一些关于这个文件内容的操作,不然就继续做其他的工作,循环往复.
但在一个坏的场景中,你没有重计算的工作要去做,而是需要去读取另一个文件B.
那除了等待他们还有什么事要做呢?
没有了,你的程序就进入了一个死循环,判断文件A是否被读取完毕,接着再去判断文件B,一遍又一遍.
要么你使用简单的状态轮询,这会导致过多消耗CPU,或者你手动加入一些随意的休眠时间,不过这也意味着你将延迟知道IO完成,这会降低程序的吞吐.
为了避免这个问题,你可以使用多路复用IO来代替.
他所做的是你再次阻塞在IO上,但这次不仅仅是一个一个的IO操作,你可以将所有需要的IO操作塞入队列,阻塞在所有的操作上. 当其中有一个IO完成之后OS会唤醒你.
一些多路复用的实现提供了更多的控制,你可以设置在特定一些IO操作完成之后再被唤醒,例如A和C文件或B和D文件完成的时候.
所有你可以调用非阻塞读取文件A,然后非阻塞读取文件B,最后告诉操作系统将我的线程置于休眠,当A和B的IO都完成的时候或其中一个完成的时候再唤醒他.
异步
多路复用IO的问题是在IO完毕前你还是处于休眠状态.
又一次,这对一些程序来说可行,那些除了等待IO操作完成外没有其他操作要去执行的程序.
但有时候,你确实需要去做其他事情.
可能你正在计算PI的数字,同时也在汇总一些文件的值.
你想要进行的操作是将所有的读操作入队列,当等待他们读取完成前,你可以继续计算PI.当一个文件读取完成后,你可以汇总他的值,然后继续进行PI的计算直到另一个文件完成读取.
为了让这可行,你需要一种方式当IO完成时中断PI的计算,并且你需要IO来执行这个操作当他完成时.
这通过事件回调完成.执行读操作的调用会需要一个回调,并且调用立即返回.当IO完成时,操作系统会挂起你的线程,并执行你的回调.当回调完成时,他会恢复你的线程.
多线程 vs 单线程?
你可能已经注意到我所描述的所有线程都是关于单个线程的,也就是你的主线程.
真相是,IO的执行不依赖于线程,这我在最开始就已经解释过了,外围设备都是在他们自己的电路里异步执行IO.
所以阻塞,非阻塞,多路复用和异步IO都是可能在单线程模型中被执行的.
这也是为什么并发IO可以不借助于多线程支持来工作.
现在,对于处理IO操作完成的结果,或者请求IO操作很明显是可以多线程的,如果你需要的话.这允许你在并发IO之上执行并发计算.所以没有什么东西阻止多线程和这些IO机制结合.
事实上,这里也有第五种受欢迎的基于多线程的IO.
他经常被混淆为非阻塞IO或异步IO,因为他对外暴露出的是类似他们的接口.
真相是,他是假装的非阻塞或异步IO.他的工作方式很简单,他使用阻塞IO,但是每个阻塞操作都是在他自己的线程中(注:多线程环境,非主线程中).
现在取决于他的实现机制,他要么接收一个回调,或者使用一种轮询模型,比如返回一个Future对象.
最后
我希望这篇文章可以帮助你澄清对多种IO的理解.还有很重要的一点需要注意,他们不是被所有的操作系统和所有的外围设备支持的.相似的,不是所有的编程语言都暴露了操作系统支持的所有IO类型的API.
这边请,所有类型的IO都解释了.
希望能对你有所帮助.
更多阅读
non-blocking IO vs async IO and implementation in Java
Asynchronous and non-blocking IO
Asynchronous I/O and event notification on linux
What is the status of POSIX asynchronous I/O (AIO)?
Kernel Asynchronous I/O (AIO) Support for Linux
免责声明
我不是一个系统层面的程序员,我也不是一个操作系统提供的所有种类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,进程的三态,同步异步阻塞非阻塞
1.操作系统历史 2.进程,IO,同步异步阻塞非阻塞 操作系统历史: 手工操作: 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念. 手工操 ...
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)
IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...
- 理解同步,异步,阻塞,非阻塞,多路复用,事件驱动IO
以下是IO的一个基本过程 先理解一下用户空间和内核空间,系统为了保护内核数据,会将寻址空间分为用户空间和内核空间,32位机器为例,高1G字节作为内核空间,低3G字节作为用户空间.当用户程序读取数据的时 ...
- 阻塞IO、非阻塞IO的区别
1.类与类之间的关系:依赖,实现,泛化(继承),关联,组合,聚合. 1)依赖(虚线):一个类是 另一个类的函数参数 或者 函数返回值. 2)实现(实线加小圆):对纯虚函数类(抽象类)的实现. 3)继承 ...
- 阻塞IO、非阻塞IO、同步IO、异步IO等
https://www.cnblogs.com/zingp/p/6863170.html 阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 4 select/poll/epoll的区别 ...
- python开发IO模型:阻塞&非阻塞&异步IO&多路复用&selectors
一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...
- 关于IO的同步,异步,阻塞,非阻塞
上次写了一篇文章:Unix IO 模型学习.恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现.中途正好讨论了网络IO的同步.异步.阻塞.非 ...
随机推荐
- Java 学习笔记 (六) Java 定义变量
这个问题来自于head first一书page68. package com.idea.study; public class Books { //headfirst page68 String ti ...
- kv.go
package clientv3 import ( pb "github.com/coreos/etcd/etcdserver/etcdserverpb" //protob ...
- java.lang.IllegalArgumentException异常 数据库别名问题
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expect ...
- docker开机自动重启参数
docker run -ti -d --privileged --restart=always -p : -p : -v /apps/qkaoauth:/apps/qkaoauth docker.qk ...
- 【差分+前缀和】BZOJ1637: [Usaco2007 Mar]Balanced Lineup
Description Farmer John 决定给他的奶牛们照一张合影,他让 N (1 ≤ N ≤ 50,000) 头奶牛站成一条直线,每头牛都有它的坐标(范围: 0..1,000,000,000 ...
- BZOJ_3747_[POI2015]Kinoman_线段树
BZOJ_3747_[POI2015]Kinoman_线段树 Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放 ...
- 【爆料】-《悉尼科技大学毕业证书》UTS一模一样原件
☞悉尼科技大学毕业证书[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归 ...
- 基于SpringBoot从零构建博客网站 - 整合lombok和mybatis-plus提高开发效率
在上一章节中<技术选型和整合开发环境>,确定了开发的技术,但是如果直接这样用的话,可能开发效率会不高,为了提高开发的效率,这里再整合lombok和mybatis-plus两个组件. 1.l ...
- 使用BeetleX的TcpBenchmark工具进行百万设备模拟测试
其实TCP测试的工具有很多,那BeetleX工具所提供的特点又是什么呢?如果你需数十万的请求或模拟上百万的设备连接,那这个工具相信可以满足你的需要!工具是基于BeetleX的基础功能扩展,支持多IP绑 ...
- 频率学派与贝叶斯学派(先验分布与后验分布,MLE和MAP)
频率学派(古典学派)和贝叶斯学派是数理统计领域的两大流派. 这两大流派对世界的认知有本质的不同:频率学派认为世界是确定的,有一个本体,这个本体的真值是不变的,我们的目标就是要找到这个真值或真值所在的范 ...