当前位置: 首页 > news >正文

同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

POSIX

同步IO、异步IO、阻塞IO、非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下。

POSIX(可移植操作系统接口)把同步IO操作定义为导致进程阻塞直到IO完成的操作,反之则是异步IO

按POSIX的描述似乎把同步和阻塞划等号,异步和非阻塞划等号,但是为什么有的人说同步IO不等于阻塞IO呢?先来说说几种常见的IO模型吧。

IO模型

这里统一使用Linux下的系统调用recv作为例子,它用于从套接字上接收一个消息,因为是一个系统调用,所以调用时会从用户进程空间切换到内核空间运行一段时间再切换回来。默认情况下recv会等到网络数据到达并且复制到用户进程空间或者发生错误时返回,而第4个参数flags可以让它马上返回。

  • 阻塞IO模型

使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。A同学用杯子装水,打开水龙头装满水然后离开。这一过程就可以看成是使用了阻塞IO模型,因为如果水龙头没有水,他也要等到有水并装满杯子才能离开去做别的事情。很显然,这种IO模型是同步的。

image

  • 非阻塞IO模型

改变flags,让recv不管有没有获取到数据都返回,如果没有数据那么一段时间后再调用recv看看,如此循环。B同学也用杯子装水,打开水龙头后发现没有水,它离开了,过一会他又拿着杯子来看看……在中间离开的这些时间里,B同学离开了装水现场(回到用户进程空间),可以做他自己的事情。这就是非阻塞IO模型。但是它只有是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间(等着水将水杯装满),因此它还是同步IO。

image

  • 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同学哪几个水龙头有水了,不需要一个个打开看(当然还有其它区别)。

image

  • 信号驱动IO模型

通过调用sigaction注册信号函数,等内核数据准备好的时候系统中断当前程序,执行信号函数(在这里面调用recv)。D同学让舍管阿姨等有水的时候通知他(注册信号函数),没多久D同学得知有水了,跑去装水。是不是很像异步IO?很遗憾,它还是同步IO(省不了装水的时间啊)。

image

  • 异步IO模型

调用aio_read,让内核等数据准备好,并且复制到用户进程空间后执行事先指定好的函数。E同学让舍管阿姨将杯子装满水后通知他。整个过程E同学都可以做别的事情(没有recv),这才是真正的异步IO。

image

总结

IO分两阶段:

1.数据准备阶段
2.内核空间复制回用户进程缓冲区阶段

一般来讲:阻塞IO模型、非阻塞IO模型、IO复用模型(select/poll/epoll)、信号驱动IO模型都属于同步IO,因为阶段2是阻塞的(尽管时间很短)。只有异步IO模型是符合POSIX异步IO操作含义的,不管在阶段1还是阶段2都可以干别的事。

  • ps:以上图片均截自UNIX网络编程卷1。

转载于:https://www.cnblogs.com/micro-chen/p/10700137.html

相关文章:

  • 生产巡检
  • Android 内存监测工具 DDMS
  • Go语言介绍
  • 多态的应用-例子
  • Redis实战 - 3.Hash
  • session的使用
  • C++ string使用
  • 外连接查询
  • C#中三层架构UI、BLL、DAL、Model实际操作
  • Opencart3.0 本地环境 前台无法提交订单
  • springcloud(六)-Ribbon配置自定义算法
  • NABCD分析---校园服务
  • go语言学习逻辑运算符if判断,iota的理解
  • actuator与spring-boot-admin 可以说的秘密
  • mongodb排序限制输出, 分组查询,爬虫连接mongodb
  • Google 是如何开发 Web 框架的
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • avalon2.2的VM生成过程
  • classpath对获取配置文件的影响
  • Git同步原始仓库到Fork仓库中
  • JavaScript HTML DOM
  • Java基本数据类型之Number
  • JWT究竟是什么呢?
  • swift基础之_对象 实例方法 对象方法。
  • 包装类对象
  • 不上全站https的网站你们就等着被恶心死吧
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 力扣(LeetCode)21
  • 批量截取pdf文件
  • 扑朔迷离的属性和特性【彻底弄清】
  • 微信小程序设置上一页数据
  • 消息队列系列二(IOT中消息队列的应用)
  • 一个项目push到多个远程Git仓库
  • k8s使用glusterfs实现动态持久化存储
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • ​linux启动进程的方式
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • ​水经微图Web1.5.0版即将上线
  • #LLM入门|Prompt#3.3_存储_Memory
  • #QT项目实战(天气预报)
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (31)对象的克隆
  • (6)STL算法之转换
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (C语言)fread与fwrite详解
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (推荐)叮当——中文语音对话机器人
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)Linux下编译安装log4cxx
  • (转)创业家杂志:UCWEB天使第一步