【图解IO与Netty系列】IO的同步与异步、阻塞与非阻塞,Linux五种IO模型

IO的同步与异步、阻塞与非阻塞,Linux五种IO模型

  • IO的同步与异步,阻塞与非阻塞
    • 阻塞IO与非阻塞IO
    • 同步IO与异步IO
  • Linux五种IO模型
    • BIO
    • NIO
    • IO多路复用
    • 信号驱动IO
    • AIO

IO的同步与异步,阻塞与非阻塞

我们有时会看到类似于同步阻塞式IO、同步非阻塞式IO、异步IO等这些名词。

大多数时候,同步就是阻塞的,异步就是非阻塞的,比如我们并发编程里面加锁进行同步,那么获取不到锁的就要阻塞等待。但是在IO里面,同步异步与阻塞非阻塞不是同一概念。

这里面的同步、异步、阻塞、非阻塞是什么意思呢?

阻塞IO与非阻塞IO

在IO里面,当数据还没有就绪时,当前线程是否需要等待数据到达,可以分为阻塞IO与非阻塞IO。阻塞式IO是指当数据未就绪时,当前线程阻塞等待数据就绪;非阻塞式IO是指当数据未就绪时,当前线程不会阻塞等待数据就绪。

在这里插入图片描述

这里的数据就绪是指,数据已经加载到操作系统内核空间。比如网络IO,当数据到达网卡缓冲区,会通过DMA(Direct Memory Access——直接内存访问)设备把数据拷贝到内核空间,此时代表数据就绪,也就是等待应用程序拷贝到用户空间。

在这里插入图片描述

同步IO与异步IO

当数据已经达到了之后,就需要把内核空间的数据拷贝到用户空间,把内核空间的数据拷贝到用户空间是通过CPU进行拷贝。

在这里插入图片描述

是否需要当前线程主动去把内核空间中的数据搬运到用户空间,这又分为同步IO和异步IO。需要当前线程主动拷贝内核空间的数据到用户空间的叫同步读取,不需要当前线程主动拷贝内核空间的数据到用户空间的叫异步读取。

在这里插入图片描述

那么,根据同步与异步、阻塞与非阻塞,就组合出了四种类型的IO:

在这里插入图片描述

首先这里要知道,异步阻塞IO是不存在的,因此阻塞式IO在数据未就绪前是阻塞等待的,直到数据就绪之后当前线程才解阻塞,而数据都已经到达了,那直接拷贝到用户空间就可以了,这时候弄一个异步读取就没有必要了。

Linux五种IO模型

BIO

BIO是同步阻塞式IO。以网络IO为例,当客户端没有发送数据时,当前线程会阻塞等待数据,当客户端发送的数据被网卡接收并被DMA设备拷贝到内核空间之后,当前线程把内核空间中的数据拷贝到用户空间,然后当前线程才从数据拷贝中返回。

在这里插入图片描述

那么我们看到的现象就是,当服务端调用read()函数时,服务端当前线程阻塞等待客户端发送数据,当客户端发送的数据被服务端接收并拷贝到内核空间之后,服务端的当前线程需要把数据拷贝到用户空间,然后服务端当前线程才从read()函数返回。

在这里插入图片描述

NIO

NIO是同步非阻塞IO,当客户端没有发送数据时,服务端线程不会阻塞等待,而是马上返回,当前线程需要不断的检测数据是否已经到达并被拷贝到内核空间。如果数据还没有准备好,那么read函数调用会马上返回一个error,用户线程可以再次发起read函数调用继续检测;如果数据已经在内核空间了,那么当前线程调用read函数就会拷贝内核空间的数据到用户空间,这个拷贝的过程是同步读取,是当前线程主动拷贝的,因此在线程拷贝数据到用户空间的这段时间,程序是不会往下执行的。

在这里插入图片描述

NIO相比BIO的不同在于当数据还未就绪时,使用NIO是不会导致当前线程阻塞的,但是当数据就绪时,NIO与BIO一样是由当前线程拷贝到用户空间的,因此当要拷贝内核空间的数据到用户空间时,NIO与BIO是一样的会卡住直到数据拷贝完毕。

在这里插入图片描述

IO多路复用

在Linux操作系统上面,IO多路复用通过Linux提供的select、poll、epoll等API实现。使用IO多路复用是会使得当前线程阻塞的,但是IO多路复用与阻塞IO不同,阻塞IO是当前线程阻塞监听一个socket文件描述符,而IO多路复用则是阻塞监听多个socket文件描述符。

在这里插入图片描述

当有一个或多个文件描述符有数据就绪时,则该线程解阻塞,可以操作这些有数据就绪的socket文件描述符读取数据。

在这里插入图片描述

信号驱动IO

要理解信号驱动IO,首先要理解什么是信号驱动。信号驱动是一种软中断,是在软件层面模拟硬件中断实现的一种中断机制。

首先当前线程向操作系统注册一个信号处理函数,操作系统内核保持该信号处理函数。

在这里插入图片描述

当对应的事件发生时,操作系统向当前线程发送一个SIGIO信号。然后触发一个软中断,当前线程切换到内核态,执行之前注册的信号处理函数。执行完毕之后,再切换回用户态,当前线程从中断处开始往下执行。

在这里插入图片描述

可见这是一种异步操作,再对应的事件没有发生时,当前线程可以继续往下执行,不会阻塞,当对应的事件发生时,才转而执行预先注册的函数。

信号驱动IO也是一种同步非阻塞IO。当前线程通过sigaction函数注册一个SIGIO信号处理函数,然后回马上返回不会阻塞。如果客户端发送的数据已被拷贝到内核空间,操作系统会发送一个SIGIO信号给当前线程,当前线程转而执行之前注册的SIGIO信号处理函数,里面会调用redvfrom读取内核空间的数据到用户空间,此时是由当前线程主动拷贝数据,因此从内核空间拷贝数据到用户空间期间当前线程阻塞,因此还是同步IO。

在这里插入图片描述

AIO

AIO是异步IO,异步IO是全程无阻塞的IO操作,性能最高。应用程序不需要阻塞等待数据到达,当数据到达时操作系统自动把内核空间的数据拷贝到用户空间,再通知当前线程处理数据。

在这里插入图片描述

首先用户线程调用aio_read函数并传递用户空间缓存区、缓冲区大小等参数,然后马上返回,不会阻塞当前线程。当数据已在内核空间中就绪时,操作系统内核自动把数据拷贝到指定的用户空间缓冲区。当操作系统内核拷贝数据到用户空间完成后,再发送一个信号通知用户线程处理数据。

在这里插入图片描述

但可惜的是,Linux操作系统对AIO的支持不是很好,Linux的AIO是基于IO多路复用做的封装,性能并没有很大的提升,因此使用的更多的是IO多路复用。但是Windows操作系统则在真正意义上实现了AIO,因此在Windows操作系统环境下使用AIO的话,可以在性能上得到很大的提升。

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

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

相关文章

(避坑)SpringSecurity关于使用.antMatchers放行接口不生效问题

问题 在使用SpringSecurity的时候发现放行指定接口一直没有生效,使用"/**"就可以生效的问题 关于securityConfig的配置代码 Beanprotected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.csrf().disable() // 关闭csrf防护…

博客开始使用 Cache Master 缓存插件

明月在给大家推荐 Cache Master 插件的时候(可参考【推荐个比较纯正的缓存插件——Cache Master】一文),仅仅是在其他站点上试用了一下,今天明月正式在博客上用上了 Cache Master,没有想到对 Dragon 主题的支持竟然是出…

Java中的泛型擦除(Type Erasure)详解

在Java编程中,泛型(Generics)是一个强大的工具,它允许程序员在编写代码时定义和使用类型参数,从而编写更灵活、可重用的代码。然而,Java的泛型实现有一个重要的特点,即类型擦除(Type…

RUST 和 GO 如何管理它们的内存

100编程书屋_孔夫子旧书网 Go 中的内存管理 Go 中的内存不会在缓存键被驱逐时立即释放。 相反,垃圾收集器会经常运行以发现任何没有引用的内存并释放它。 换句话说,内存会一直挂起,直到垃圾收集器可以评估它是否真正不再使用,而…

rtsp协议分析

rtsp概述 rtsp (real-time stream protocol)实时流媒体控制协议。RFC2326:这是RTSP的初始定义版本v1.0,由哥伦比亚大学、网景和RealNetworks公司提交给互联网工程任务组(IETF)作为RFC标准。RFC7826:这是RTSP的后续更新…

Java进阶学习笔记14——模板方法设计模式

面试和看源码。 谈到设计模式: 1、解决了什么问题? 2、怎么写? 模板方法设计模式解决了什么问题? 解决方法中存在重复代码的问题。 写法: 1)定义一个抽象类: 2)在里面定义两个方…

JAVA面试题大全(十五)

1、Zookeeper 是什么? zookper是一个分布式的,开放源码的分布式应用程序协调服务。是 google chubby 的开源实现,是 hadoop 和 hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护…

C# 控制台应用模板可生成顶级语句

C# 控制台应用模板可生成顶级语句 项目2024/01/0810 个参与者 反馈 本文内容 使用新的程序样式隐式 using 指令全局 using 指令使用旧程序样式 从 .NET 6 开始,新 C# 控制台应用的项目模板在 Program.cs 文件中生成以下代码: C#复制 // See https…

C++ prime 第五版 第14章 重载运算与类型转换

一、基本概念 重载的运算符是具有特殊名字的函数:它们的名字由关键字operator和其后要定义的运算符号共同组成。和其他函数一样,重载的运算符也包含返回类型、参数列表以及函数体。 我们不能为内置类型的运算对象重定义运算符。对于一个运算符函数来说&…

某方protobuf闲谈

问题 当我们去看某方的时候,搜索了关键词svm,然后通过抓包查看,请求的Request Payload是一串看不懂的乱码,并且返回的数据也大部分是乱码 观察请求的Content-Type是application/grpc-web+proto,没错数据的传输是protobuf的形式了 protobuf的相关概念和原理,网上有很多教…

vulhub——Aria2、bash、catic

文章目录 一、Aria2 任意文件写入漏洞二、CVE-2014-6271(Bash Shell 漏洞)三、CVE-2022-46169(Cacti 前台命令注入漏洞) 一、Aria2 任意文件写入漏洞 Aria2是一个命令行下轻量级、多协议、多来源的下载工具(支持 HTTP…

conda create,conda:未找到命令,ubantu添加环境变量,make工具是什么,docker工具什么,

目录 conda create -n flock_client python==3.11 conda:未找到命令,ubantu添加环境变量 添加conda到系统路径

docker-compose 搭建 单机版ELK

docker-compose 搭建 单机版ELK 前言 本次部署将使用ElasticSearch官方的镜像和Docker-Compose来创建单节点的ELK,用于学习ELK操作。在k8s集群内,如果每天的日志量超过20G以上,建议部署在k8s集群外部,以支持分布式集群的架构。在…

Flutter 中的 RepaintBoundary 小部件:全面指南

Flutter 中的 RepaintBoundary 小部件:全面指南 在Flutter的高性能渲染体系中,RepaintBoundary是一个重要的优化工具。它允许开发者将复杂的组件分割成独立的部分,以减少不必要的重绘,从而提高应用的性能。本文将提供RepaintBoun…

11|数据库编程:包括数据库的基本概念,JDBC的使用,数据库连接池的实现,Hibernate和MyBatis的应用等。

数据库基本概念 想象你有一个装满宝藏的箱子,里面放着各种宝贝,但这些宝贝都按照一定规则摆放。数据库就像是这样一个箱子,但它存放的是信息,比如姓名、年龄、电子邮件等。它帮我们有条理地管理数据,让我们可以方便地…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第26节-内嵌blender展厅

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第26节-内嵌blender展厅 使用dtns.network德塔世界(开源的智体世界引擎),策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界…

python操作rabbitmq的consumer,并强制关闭特定consumer的连接

引入 python获取指定队列的consumer python可以使用rabbitmq_management的api获取所有consumer的信息。【队列需要安装rabbitmq_management,在大部分情况下,我们安装队列的同时,都会安装管理界面,以方便一些简单的手动操作与简单…

网络编程的基础知识(适合新手)

网络编程 在Java中,网络编程是指使用Java语言进行网络通信的编程技术。这种技术使得位于不同地理位置的计算机能够通过网络进行通信,实现资源共享和信息传递。 一、定义 Java网络编程是Java语言在网络通信方面的应用,它利用Java提供的网络…

位带操作 Bit-band

位带操作(Bit-banding)的特性是ARM Cortex-M微控制器中一个非常有用的功能,其目的是提供一种简便的方法来访问和操作存储器中单个位的状态。位带操作能够使程序员能够以原子操作(即不可中断的操作)的方式读取和写入单个…

Flutter 中的 DateRangePickerDialog 小部件:全面指南

Flutter 中的 DateRangePickerDialog 小部件:全面指南 在 Flutter 应用开发中,日期和时间的选择是一项常见的用户交互需求。DateRangePickerDialog 是一个方便的小部件,它提供了一个对话框界面,允许用户选择日期范围。这个小部件…