IO - 同步,异步,阻塞,非阻塞
同步synchronous IO和异步asynchronous IO阻塞blocking IO和非阻塞non-blockingIO分别是什么到底有什么区别这个问题其实不同的人给出的答案都可能不同比如wiki就认为asynchronous IO和non-blocking IO是一个东西。这其实是因为不同的人的知识背景不同并且在讨论这个问题的时候上下文(context)也不相同。所以为了更好的回答这个问题我先限定一下本文的上下文。本文讨论的背景是Linux环境下的network IO。本文最重要的参考文献是Richard Stevens的“UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”6.2节“I/O Models ”Stevens在这节中详细说明了各种IO的特点和区别如果英文够好的话推荐直接阅读。Stevens的文风是有名的深入浅出所以不用担心看不懂。本文中的流程图也是截取自参考文献。Stevens在文章中一共比较了五种IO Modelblocking IOnonblocking IOIO multiplexingsignal driven IOasynchronous IO由于signal driven IO在实际中并不常用所以我这只提及剩下的四种IO Model。再说一下IO发生时涉及的对象和步骤。对于一个network IO (这里我们以read举例)它会涉及到两个系统对象一个是调用这个IO的process (or thread)另一个就是系统内核(kernel)。当一个read操作发生时它会经历两个阶段1 等待数据准备 (Waiting for the data to be ready)2 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)记住这两点很重要因为这些IO Model的区别就是在两个阶段上各有不同的情况。blocking IO在linux中默认情况下所有的socket都是blocking一个典型的读操作流程大概是这样当用户进程调用了recvfrom这个系统调用kernel就开始了IO的第一个阶段准备数据。对于network io来说很多时候数据在一开始还没有到达比如还没有收到一个完整的UDP包这个时候kernel就要等待足够的数据到来。而在用户进程这边整个进程会被阻塞。当kernel一直等到数据准备好了它就会将数据从kernel中拷贝到用户内存然后kernel返回结果用户进程才解除block的状态重新运行起来。所以blocking IO的特点就是在IO执行的两个阶段都被block了。non-blocking IOlinux下可以通过设置socket使其变为non-blocking。当对一个non-blocking socket执行读操作时流程是这个样子从图中可以看出当用户进程发出read操作时如果kernel中的数据还没有准备好那么它并不会block用户进程而是立刻返回一个error。从用户进程角度讲 它发起一个read操作后并不需要等待而是马上就得到了一个结果。用户进程判断结果是一个error时它就知道数据还没有准备好于是它可以再次发送read操作。一旦kernel中的数据准备好了并且又再次收到了用户进程的system call那么它马上就将数据拷贝到了用户内存然后返回。所以用户进程其实是需要不断的主动询问kernel数据好了没有。IO multiplexingIO multiplexing这个词可能有点陌生但是如果我说selectepoll大概就都能明白了。有些地方也称这种IO方式为event driven IO。我们都知道select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket当某个socket有数据到达了就通知用户进程。它的流程如图当用户进程调用了select那么整个进程会被block而同时kernel会“监视”所有select负责的socket当任何一个socket中的数据准备好了select就会返回。这个时候用户进程再调用read操作将数据从kernel拷贝到用户进程。这个图和blocking IO的图其实并没有太大的不同事实上还更差一些。因为这里需要使用两个system call (select 和 recvfrom)而blocking IO只调用了一个system call (recvfrom)。但是用select的优势在于它可以同时处理多个connection。多说一句。所以如果处理的连接数不是很高的话使用select/epoll的web server不一定比使用multi-threading blocking IO的web server性能更好可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快而是在于能处理更多的连接。在IO multiplexing Model中实际中对于每一个socket一般都设置成为non-blocking但是如上图所示整个用户的process其实是一直被block的。只不过process是被select这个函数block而不是被socket IO给block。Asynchronous I/Olinux下的asynchronous IO其实用得很少。先看一下它的流程用户进程发起read操作之后立刻就可以开始去做其它的事。而另一方面从kernel的角度当它受到一个asynchronous read之后首先它会立刻返回所以不会对用户进程产生任何block。然后kernel会等待数据准备完成然后将数据拷贝到用户内存当这一切都完成之后kernel会给用户进程发送一个signal告诉它read操作完成了。到目前为止已经将四个IO Model都介绍完了。现在回过头来回答最初的那几个问题blocking和non-blocking的区别在哪synchronous IO和asynchronous IO的区别在哪。先回答最简单的这个blocking vs non-blocking。前面的介绍中其实已经很明确的说明了这两者的区别。调用blocking IO会一直block住对应的进程直到操作完成而non-blocking IO在kernel还准备数据的情况下会立刻返回。在说明synchronous IO和asynchronous IO的区别之前需要先给出两者的定义。Stevens给出的定义其实是POSIX的定义是这样子的A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;An asynchronous I/O operation does not cause the requesting process to be blocked;两者的区别就在于synchronous IO做”IO operation”的时候会将process阻塞。按照这个定义之前所述的blocking IOnon-blocking IOIO multiplexing都属于synchronous IO。有人可能会说non-blocking IO并没有被block啊。这里有个非常“狡猾”的地方定义中所指的”IO operation”是指真实的IO操作就是例子中的recvfrom这个system call。non-blocking IO在执行recvfrom这个system call的时候如果kernel的数据没有准备好这时候不会block进程。但是当kernel中数据准备好的时候recvfrom会将数据从kernel拷贝到用户内存中这个时候进程是被block了在这段时间内进程是被block的。而asynchronous IO则不一样当进程发起IO 操作之后就直接返回再也不理睬了直到kernel发送一个信号告诉进程说IO完成。在这整个过程中进程完全没有被block。各个IO Model的比较如图所示经过上面的介绍会发现non-blocking IO和asynchronous IO的区别还是很明显的。在non-blocking IO中虽然进程大部分时间都不会被block但是它仍然要求进程去主动的check并且当数据准备完成以后也需要进程主动的再次调用recvfrom来将数据拷贝到用户内存。而asynchronous IO则完全不同。它就像是用户进程将整个IO操作交给了他人kernel完成然后他人做完后发信号通知。在此期间用户进程不需要去检查IO操作的状态也不需要主动的去拷贝数据。最后再举几个不是很恰当的例子来说明这四个IO Model:有ABCD四个人在钓鱼A用的是最老式的鱼竿所以呢得一直守着等到鱼上钩了再拉杆B的鱼竿有个功能能够显示是否有鱼上钩所以呢B就和旁边的MM聊天隔会再看看有没有鱼上钩有的话就迅速拉杆C用的鱼竿和B差不多但他想了一个好办法就是同时放好几根鱼竿然后守在旁边一旦有显示说鱼上钩了它就将对应的鱼竿拉起来D是个有钱人干脆雇了一个人帮他钓鱼一旦那个人把鱼钓上来了就给D发个短信。————————————————原文链接https://blog.csdn.net/historyasamirror/article/details/5778378

相关新闻

Unity游戏开发从入门到精通:构建技能金字塔与实战路径

Unity游戏开发从入门到精通:构建技能金字塔与实战路径

1. 项目概述:为什么Unity值得你投入时间?如果你对游戏开发、交互式内容创作,或者仅仅是“创造一个属于自己的虚拟世界”抱有热情,那么Unity引擎几乎是你绕不开的一个名字。它早已不是那个只被独立开发者用来制作2D小游戏的工具了。…

2026/9/23 5:36:37 阅读更多 →
JavaSE:基础入门(一)

JavaSE:基础入门(一)

1、关键字 被java赋予特定含义的单词,特点:全部都是小写 以下是java的关键字列表,先了解下即可,其中void就是关键字,而 Void就不是关键字,只是一个占位符的类 访问控制 private protected public类,方法和变量修…

2026/9/23 1:49:26 阅读更多 →
Godot 4 AnimatedSprite2D 实战:让待机与移动动画自动切换

Godot 4 AnimatedSprite2D 实战:让待机与移动动画自动切换

Godot 4 AnimatedSprite2D 实战:让待机与移动动画自动切换角色已经能移动,但如果始终显示同一张图片,游戏仍会显得像在拖动贴纸。AnimatedSprite2D 可以用一个 SpriteFrames 资源管理多组逐帧动画,再根据角色的真实速度切换 idle …

2026/9/23 23:09:30 阅读更多 →

最新新闻

AI工程全景地图:六步构建从数据到价值的落地路径

AI工程全景地图:六步构建从数据到价值的落地路径

1. 为什么突然都在说 AI 工程这几年“AI 工程”这个词出现频率越来越高,但你要是真去问一句“AI 工程到底是什么”,能一句话说清楚的人其实不多。我见过不少团队,模型训练得挺溜,一到上线就翻车,不是推理延迟压不下来&…

2026/9/24 20:48:59 阅读更多 →
jsonschema实战:为JSON数据立规矩的Python校验库

jsonschema实战:为JSON数据立规矩的Python校验库

我们天天和数据打交道,但真正让你头疼的往往不是“数据对不对”,而是“数据是不是你要的那个结构”。JSON 格式灵活得让人又爱又恨,前端传参少个字段、API 响应多了个 null、配置文件类型悄悄从 int 变成 string,这些坑想必大家都…

2026/9/24 20:48:59 阅读更多 →
Codex Token消耗优化:两个开源工具让账单减半

Codex Token消耗优化:两个开源工具让账单减半

先说结论:Codex 确实好用,但它烧起 Token 来也真的一点都不含糊。我重度用了几个月之后,账单上的数字一度让我怀疑是不是把 API Key 泄露了。后来我才意识到,问题不在于 Codex 本身有多能吃,而在于我们喂给它的“上下文…

2026/9/24 20:48:59 阅读更多 →
GPT金融AI量化投资实战:从信息提取到策略辅助的工程化探索

GPT金融AI量化投资实战:从信息提取到策略辅助的工程化探索

1. 从标题出发:这个项目到底在做什么“开启GPT技术与金融AI投资探索之旅”这个标题,乍一看像是某个课程或者训练营的宣传语,但如果你真的动手去拆,会发现它其实指向一个非常具体的技术落地场景:用大语言模型的能力去辅…

2026/9/24 20:48:59 阅读更多 →
AI室内设计会改结构吗?四款工具实测与避坑指南

AI室内设计会改结构吗?四款工具实测与避坑指南

1. 从一张户型图说起:AI室内设计到底动了什么很多人第一次用AI做室内设计,心里都揣着同一个疑问:我把户型图丢进去,它会不会自作主张把承重墙砸了、把窗户挪了、把卫生间改到客厅中间?这个担心不是多余的。我前后用四款…

2026/9/24 20:48:59 阅读更多 →
使用 @openuidev/devtools 调试 OpenUI 应用:Inspect 事件面板与 Debug 工作台实战指南

使用 @openuidev/devtools 调试 OpenUI 应用:Inspect 事件面板与 Debug 工作台实战指南

使用 openuidev/devtools 调试 OpenUI 应用:Inspect 事件面板与 Debug 工作台实战指南 【免费下载链接】openui The Open Standard for Generative UI 项目地址: https://gitcode.com/gh_mirrors/openui1/openui openuidev/devtools 是 OpenUI 生态中的开发期…

2026/9/24 20:47:58 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →