BIO NIO AIO之间的区别与联系

news2025/1/10 11:45:35

目录

  • 前言
  • 五种I/O模型
    • 1.同步阻塞I/O, BIO
    • 2.同步非阻塞I/O, NIO
    • 3.多路复用IO
    • 4.信号驱动I/O
    • 5.异步I/O,AIO
  • 同步=阻塞?异步=非阻塞?
    • 1.阻塞I/O 与 非阻塞I/O
    • 2.同步I/O 与 异步I/O
  • Netty采用了哪种I/O模型?

前言

  1. Unix系统下的五种基本I/O模型
  • blocking I/O(同步阻塞IO,BIO)
  • nonblocking I/O(同步非阻塞IO,NIO)
  • I/O multiplexing (I/O多路复用)
  • signal driven I/O(信号驱动I/O)
  • asynchronous I/O(异步I/O,AIO)
  1. 当一次网络IO发生时,主要涉及到三个对象:
  • 发起此次IO操作的Process或者Application
  • 系统内核kernel。用户进程无法直接操作I/O设备,必须通过系统内核kernel与I/O设备交互。
  • I/O设备,包括网络、磁盘等。本文主要针对网络。
    在这里插入图片描述
  1. 真正的I/O过程,主要分为两个阶段:
  • 等待数据准备阶段。
  • 数据拷贝阶段。数据准备完毕,从内核kernel拷贝到进程process中

以一个socket上的输入操作为例:
第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。
第二步就是把数据从内核缓冲区复制到用户态缓冲区。

五种I/O模型

1.同步阻塞I/O, BIO

  1. 我们一般使用最多的,最基础的I/O模型就是同步阻塞I/O。
    典型应用:阻塞socket、Java BIO
    在这里插入图片描述

  2. BIO的过程:

  • 应用进程向内核发起 I/O 请求,发起调用的线程 一直阻塞,等待内核返回结果。
  • 数据准备完毕,从内核kernel拷贝到用户态内存(仍旧阻塞),然后kernel返回结果,用户进程process结束阻塞,重新运行。

BIO的特点就是在IO执行的 两个阶段 都被 阻塞

  1. 为了提高性能,常见的优化方式就是采用多线程
    在一般的场景中,多线程模型下的BIO是成本较低、收益较高的方式。但是,如果在高并发的场景下,过多的创建线程,会严重占据系统资源,降低系统对外界响应效率。“池化”的目的在于减少创建和销毁线程的频率,让空闲的线程重新承担新的执行任务,维持一个合理的线程数量,可以很好的降低系统开销。但是,“池化”技术只能一定程度上缓解了频繁调用IO接口带来的资源占用。如果“池”上限100,而我们需要1000的IO,那并不能解决性能问题,这是由于BIO模型本身的限制决定的。

2.同步非阻塞I/O, NIO

典型应用:socket的非阻塞模式
在这里插入图片描述

  1. 过程
    应用进程向内核发起 I/O 请求后,如果kernel中的数据还没有准备好,不再会“阻塞”等待结果,而是会立即返回。从用户进程角度讲 ,它发起一个IO操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它开始发起轮训操作。直到kernel中的数据准备好了,一旦用户再轮训过来,就马上将数据拷贝到了用户内存,然后返回。所以,在非阻塞式IO中,用户进程其实是需要不断地主动询问kernel数据准备好了没有。

非阻塞NIO模型相比于BIO的显著差异在于,在“数据等待”阶段,不再“阻塞”,立即返回。但是在“数据拷贝”阶段,仍然是“阻塞”的。

  1. 虽然非阻塞模型避免了“数据等待”阶段的阻塞,但是,采用轮询方式,会导致系统上下文切换开销很大,会大幅度推高CPU 占用率。因此,单独使用非阻塞 I/O 模型的效率并不高。而且随着并发量的提升,非阻塞 I/O 会存在严重的性能浪费。我们可以看到,轮训的目的只是检测“数据是否已经就绪”,而操作系统提供了更为高效的检测接口,例如select()多路复用模式,可以一次检测多个连接是否活跃。

3.多路复用IO

  1. 多路复用实现了一个线程处理多个 I/O 句柄的操作,有些地方也称这种IO方式为事件驱动IO(event driven IO)。多路指的是多个数据通道,复用指的是使用一个或多个固定线程来处理每一个 Socket。
    典型应用:select、poll、epoll三种方案
    Java NIO
    在这里插入图片描述

  2. 过程
    多个的进程的IO可以注册到一个复用器(selector)上,然后用一个进程调用select,select会监听所有注册进来的IO。如果selector所有监听的IO在内核缓冲区都没有可读数据,select调用进程会被阻塞;同时,kernel会“监视”所有select负责的socket,如果任何一个socket中的数据准备好了,select就会返回;然后select调用进程可以自己或通知另外的进程(注册进程)来再次发起读取IO,然后process将数据从kernel拷贝到用户进程,读取内核中准备好的数据。可以看到,多个进程注册IO后,只有一个select调用进程被阻塞
    多路复用解决了同步阻塞 I/O 和同步非阻塞 I/O 的问题,是一种非常高效的 I/O 模型。我们可以直观看到,这个模型的好处在于单个process就可以同时处理多个网络连接的IO。

多路复用I/O,select阶段,对于多路socket的“数据等待”阶段而言,是“非阻塞”。对单个socket的“数据拷贝”阶段,也是“阻塞”。

  1. 注意
    如果处理的IO数不多的情况下,使用多路复用IO的web server不一定比使用 池化+BIO 的web server性能更好,可能延迟还更大。
    考虑极端情况下,只有一个IO,多路复用需要 2 次系统调用(select + recvfrom),而BIO只需要 1 次系统调用(recvfrom)。
    所以,多路复用IO的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。

4.信号驱动I/O

  1. 在使用信号驱动 I/O 时,当数据准备就绪后,内核通过发送一个 SIGIO 信号通知应用进程,应用进程就可以开始读取数据了。

在这里插入图片描述

  1. 信号驱动I/O模型的最大特点就是不需要process进程不断轮训内核是否已经准备就绪。

信号驱动I/O在"数据等待"阶段“非阻塞”。当数据准备完成后,信号通知process,process开始“数据拷贝”阶段,这里仍然是“阻塞”的。

  1. 信号驱动 I/O 有几个缺陷:
  • 在大量 IO 操作时可能会因为信号队列溢出导致没法通知。

  • 信号驱动 I/O 尽管对于处理 UDP 套接字来说有用,信号通知意味着到达一个数据报,或者返回一个异步错误。

    但是,对于 TCP 而言,信号驱动的 I/O 方式不太好用。因为导致信号通知的情况有非常多种,每一个来进行判别会消耗很大资源。
    所以信号驱动I/O模式用得非常少。而且尤其需要注意,在“数据拷贝”阶段,它仍然是“阻塞”的

5.异步I/O,AIO

  1. 真正的异步I/O,就是AIO。
    典型应用:JAVA7 AIO、高性能服务器
    在这里插入图片描述

  2. 过程
    用户进程发起I/O请求后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它收到一个请求之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它I/O操作完成了。AIO最重要的一点是 从内核缓冲区拷贝数据到用户态缓冲区的过程也是由系统异步完成,应用进程只需要在指定的数组中引用数据即可。

  3. AIO 与信号驱动 I/O 的主要区别:
    信号驱动 I/O 由内核通知何时可以开始一个 I/O 操作,而异步 I/O 由内核通知 I/O 操作何时已经完成。

"数据等待"阶段,非阻塞。"数据拷贝”阶段,非阻塞

AIO是真正的异步模型,它不会对请求进程产生任何的阻塞。

同步=阻塞?异步=非阻塞?

1.阻塞I/O 与 非阻塞I/O

结合I/O模型来说,阻塞I/O会一直block对应的进程直到操作完成,而非阻塞 IO在kernel 在"等待数据准备"阶段会立刻返回。
所以一般认为,阻塞I/O只有BIO,另外四个模型都是属于非阻塞I/O。

2.同步I/O 与 异步I/O

  1. 同步I/O 和 异步I/O 的定义是什么,根据POSIX的定义:
  • 同步I/O : A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
  • 异步I/O : An asynchronous I/O operation does not cause the requesting process to be blocked;
    两者的区别就在于同步I/O做 "IO operation”的时候会将process阻塞。
    那么按照这个定义,我们看看前面每个模型的“关键钥匙”分析部分,可以明显看到,BIO,NIO,IO多路复用、信号驱动IO 四种模型都属于 同步IO。因为它们在IO的第二阶段,真正执行“数据拷贝”的阶段,都是“阻塞”的。以NIO为例,在执行recvfrom这个系统调用的时候,如果kernel的数据没有准备好,这时候不会block进程。但是当kernel中数据准备好的时候,recvfrom会将数据从kernel拷贝到用户内存中,这个时候进程是被block了。同理,信号驱动IO,当内核中IO数据就绪时以SIGIO信号通知请求进程,请求进程再把数据从内核读入到用户空间,这一步也是阻塞的。
  1. 真正的异步I/O只有一个,就是AIO。当进程发起IO操作之后,就直接返回再也不管了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被阻塞。如定义所说,不会因为IO操作阻塞。

Netty采用了哪种I/O模型?

  1. Netty 的 I/O 模型是基于非阻塞 I/O 实现的,底层依赖的是 JDK NIO 框架的多路复用器 Selector。
    一个多路复用器 Selector 可以同时轮询多个 Channel,采用 epoll 模式后,只需要一个线程负责 Selector 的轮询,就可以接入成千上万的客户端。
  2. Netty为什么不采用AIO?
    因为 AIO 的目的是希望 I/O 线程不阻塞主线程,属于异步 I/O,由内核通知 I/O 操作何时完成。AIO 适用于连接数多的且需要长时间连接的场景。
  3. 对于AIO来说,目前操作系统支持程度有限且实现起来复杂。
    Netty也尝试过AIO,但是效果不是很理想,最终废弃了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/611089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Jenkins】什么?前端还能用Jenkins一键部署?

前置要求: Jenkins安装nodejs插件(本篇文章会教) Linux安装Node.js(图文解说详细版) 如果你是一名前端工程师,那么你可能会对Jenkins这个自动化构建工具并不陌生。但是,你有没有想过在前端项目中…

Python+Django图书商城网站前后端

程序示例精选 PythonDjango图书商城网站前后端 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonDjango图书商城网站前后端 >>编写代码&#xff0c;代码整洁&#xff0c;规…

飞行器姿态计算

在飞行器的控制中&#xff0c;姿态计算是至关重要的一步。姿态计算的目标是确定飞行器相对于参考坐标系的姿态&#xff0c;通常以欧拉角&#xff08;滚转、俯仰和偏航&#xff09;或四元数的形式表示。 以下是姿态计算的原理和常用方法的简要介绍&#xff1a; 原理&#xff1a…

数据库系列:数据库高可用及无损扩容

1 背景 在大型互联网场景中&#xff0c;数据库的高可用性显得尤为重要&#xff0c;为了保证稳定性&#xff0c;一般需要采用强化的架构模式&#xff0c;以保证数据层能够提供持续有效的稳定支撑。 2 高可用架构的基本演进过程 2.1 基本的数据库架构 每个服务对应一个存储服…

FinancesOnline 2022/2023 10大IT趋势预测

在过去几十年的时间里&#xff0c;全世界的计算能力达到了万亿倍的增长。太空、军事和工业研究促成了范式的转变。与此同时&#xff0c;新冠肺炎大流行等不可预见的事件迫使人们去迎接新的技术&#xff0c;采用与以往不同的技术路径&#xff0c;这导致了IT趋势越来越难以跟上。…

阿里云轻量服务器--Docker--Rabbitmq安装

1 Rabbitmq 介绍&#xff1a; RabbitMQ 是一个开源的消息代理软件&#xff0c;通常用于构建分布式系统&#xff0c;支持多种消息传递协议&#xff0c;并支持多种编程语言。RabbitMQ 基于 AMQP (Advanced Message Queuing Protocol) 协议开发&#xff0c;是一个高可用、高可靠、…

3.完成ODS层数据采集操作

将原始数据导入mysql 1 选中mysql 运行脚本 2 验证结果 数据存储格式和压缩方案 存储格式 分类 1.行式存储(textFile) 缺点:可读性较好 执行 select * 效率比较高 缺点:耗费磁盘资源 执行 select 字段 效率比较低 2.列式存储(orc) 优点:节省磁盘空间. 执行 select 字段…

配电网可靠性评估(4)—(顶刊复现)基于线性规划的配电网可靠性评估

之前的博客中介绍了配电网可靠性评估的三种方法、分别是解析法中的最小路法&#xff0c;以及序贯蒙特卡罗模拟法及非序贯蒙特卡洛模拟法&#xff0c;顺带提到了含有分布式电源的配电网可靠性评估方法。 配电网可靠性评估&#xff08;一&#xff09;最小路法和非序贯蒙特卡洛模…

Elai.io:AI视频生成平台

【产品介绍】 Elai.io是一个基于人工智能的AI视频生成平台&#xff0c;可以让你只用文本就能制作出有真人主持的专业视频。无论你是想做教育、营销、企业沟通或者其他类型的视频内容&#xff0c;Elai.io都可以帮你节省时间和成本&#xff0c;提高效率和质量。Elai.io的技术结合…

618数码产品攻略,列举几款2023年618必入的数码产品

​一年一度大型促销的618节日转眼间第一波就已经过去了&#xff0c;在这种各类优惠活动接踵而至的日子里&#xff0c;很多人都是准备着更换新东西的时刻&#xff0c;不过也会存在着一部分人&#xff0c;想要入手数码好物&#xff0c;但又不知道该如何去挑选&#xff0c;毕竟现在…

2.2 事件驱动的reactor网络设计模型

在网络io、io多路复用select/poll/epoll、基于事件驱动的reactor中介绍了多种网络I/O方式&#xff0c;特别是事件驱动的reactor。其开发效率比直接使用IO多路复用要高&#xff0c;它一般是单线程的&#xff0c;设计目标是希望一个线程使用CPU的全部资源。 并且&#xff0c;相对…

Rxjava2系列:RXjava2.1.7源码下载

找到github项目地址&#xff1a;https://github.com/ReactiveX/RxJava/ 找到右侧的release&#xff0c;点击打开。 搜索2.1.7 (2.1.7是这篇文章&#xff1a;RxJava 是如何实现线程切换的&#xff08;上&#xff09;的源码版本&#xff09; 找到Assert&#xff0c;下载 解…

计算机专业应届毕业生有没有必要参加IT培训?

大学学习的计算机专业&#xff0c;毕业还需要进行IT培训吗&#xff1f;我想&#xff0c;这个问题也困扰着你们吧。那今天小课就带着你们分析一下&#xff0c;计算机专业毕业的应届生到底有没有必要进行培训。 了解企业的技术需求 考虑培训不培训&#xff0c;首先要了解一下现在…

Vue.js 中的数据双向绑定是如何实现的?

Vue.js 中的数据双向绑定是如何实现的&#xff1f; Vue.js 是一款流行的前端框架&#xff0c;它的核心功能之一是数据双向绑定。本文将介绍 Vue.js 中数据双向绑定的实现原理&#xff0c;并附上相关代码实例。 什么是数据双向绑定&#xff1f; 在传统的前端开发中&#xff0c…

Matlab论文插图绘制模板第98期—大小不同多子图(Subplot)

上一篇文章分享了Matlab多子图的绘制模板&#xff1a; 但假如子图的大小不是相同的&#xff0c;该怎么操作呢&#xff1f; 本期就来分享一下大小不同多子图的绘制模板。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;…

java SSM 房屋管理系统统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM 房屋管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和 数据库&#xff0c;系统主要采用B…

Linux - 第22节 - 网络基础(其他重要协议或技术)

1.DNS协议 • DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;协议&#xff0c;是一个用来将域名转化为IP地址的应用层协议。 • DNS协议属于应用层协议&#xff0c;由UDP实现其域名解析功能。 1.1.DNS背景 TCP/IP中通过IP地址和端口号的方式&#xff0c;来…

地震勘探基础(七)之地震静校正

地震静校正 首先&#xff0c;为什么要进行地震静校正处理呢&#xff1f;主要的原因是地震勘探中激发和接收的观测面不完全是水平的。尤其是在山区、沙漠和黄土原地区。而且近地表还存在风化层或低、降速带低、降速带的厚度和速度会发生变化&#xff0c;这就导致反射波的传播时…

HTML5 FormData对象

利用FormData对象,你可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单". 创建一个FormData对象 你可以先创建一个空的FormData对象,然后使用append()方法向该对象里添加字段,如下: var oMyForm new FormData();oMyForm.append(&…

Web服务器的工作原理

Web服务器的工作原理 什么是web服务器、应用服务器和web容器&#xff1f;什么是Servlet&#xff1f;他们有什么作用&#xff1f;什么是ServletContext&#xff1f;它由谁创建&#xff1f;ServletRequest和ServletResponse从哪里进入生命周期&#xff1f;如何管理Session&#x…