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

news2024/11/13 9:39:46

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.coloradmin.cn/o/1697200.html

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

相关文章

【python】python 全国5A级景区数据采集与pyecharts可视化(源码+数据+论文)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

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

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

美甲店会员预约系统管理小程序的作用是什么

女性爱美体现在方方面面,美丽好看的指甲也不能少,市场中美甲店、小摊不少,也跑出了不少连锁品牌,70后到00后,每个层级都有不少潜在客户,商家需要获取和完善转化路径,不断提高品牌影响力与自身内…

Python学习---利用Python操作数据库

如何理解连接connection和游标 cursor? connection就像是连接出发地和目的地的高速公路cursor就像是在高速公路上的货车-拉货我们使用游标就可以完成对数据的操作当我们完成操作完成后就可以停下货车,然后公路再停止使用。 pysql实现查询 ""…

Linux基础(七):Linux 系统上的库文件生成与使用

学过C语言我们知道,C语言有标准库和自定义库,这些方便了我们的实际开发,提供了已经实现好的函数接口,我们使用的时候,只需要引入头文件即可,那具体的实现过程又是怎么样的呢?我们又该如何实现我…

[7] CUDA之常量内存与纹理内存

CUDA之常量内存与纹理内存 1. 常量内存 NVIDIA GPU卡从逻辑上对用户提供了 64KB 的常量内存空间,可以用来存储内核执行期间所需要的恒定数据常量内存对一些特定情况下的小数据量的访问具有相比全局内存的额外优势,使用常量内存也一定程序上减少了对全局…

Java进阶学习笔记24——Object类

Object类: Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法。 所有类都是Object类的子孙类。 API文档: Object类的成员方法: Object类的常见方法: Student类&…

python冰雹序列的探索与编程实现

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、冰雹序列的奥秘 二、编程实现冰雹序列 三、测试与验证 四、总结与展望 一、冰雹序列的…

pycharm配置python开发环境—miniconda+black+gitlab

下载miniconda管理python开发环境 miniconda下载地址:https://docs.anaconda.com/free/miniconda/ miniconda最新版本的python版本是python3.12.2,下载这个miniconda最新版本后,会导致执行conda create -n py31013 python3.10.13指令配置py…

基于STM32实现智能水族箱控制系统

目录 引言环境准备智能水族箱控制系统基础代码示例:实现智能水族箱控制系统 水温传感器数据读取水泵与加热器控制水位传感器数据读取用户界面与显示应用场景:水族箱管理与环境控制问题解决方案与优化收尾与总结 1. 引言 本教程将详细介绍如何在STM32嵌…

力扣刷题---2283. 判断一个数的数字计数是否等于数位的值【简单】

题目描述 给你一个下标从 0 开始长度为 n 的字符串 num &#xff0c;它只包含数字。 如果对于 每个 0 < i < n 的下标 i &#xff0c;都满足数位 i 在 num 中出现了 num[i]次&#xff0c;那么请你返回 true &#xff0c;否则返回 false 。 示例 1&#xff1a; 输入&a…

C++面向对象程序设计 - 输入和输出

程序的输入指的是文件将数据传送给程序&#xff0c;程序的输出指的是从程序将数据传送输出文件。 C的输入和和输出包括以下三个方面&#xff1a; 对系统指定的标准设备的输入和输出&#xff0c;即从键盘输入数据&#xff0c;输出到显示器屏幕。以外存磁盘&#xff08;或光盘、…

消费者相关高效读写ZK作用

消费者分区分配策略 目录概述需求&#xff1a; 设计思路1.消费者分区分配策略2. 消费者offset的存储3. kafka消费者组案例4. kafka高效读写&Zk作用5. Ranger分区再分析 实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show …

学习存储协议的利器,聊聊tcpdump和Wireshark

数据存储技术分为多个方面,包括数据持久化、数据映射、数据压缩和通信协议等等。其中通信协议是数据存储技术中非常重要的一部分,正是通信协议使得计算节点可以访问存储设备。同时,也正是不同的协议让存储系统呈现不同的形态。 如下图所示,通过iSCSI协议,可以将存储端的存…

解决Vue3+TS+vite,VSCode 高亮语法错误

一般像这种提示&#xff0c;有可能就是TypeScript语法的识别问题&#xff0c; 一般我们重装一下Vue - Official插件 或者将tcconfig.json中的moduleResolution改为node模式&#xff0c; 基本都是TypeScript无法识别vue文件中的TypeScript语句导致的

22款奔驰GLE450升级原厂AMG阀门运动排气声浪

提升车辆外观&#xff1a;空气悬挂系统可以调节车辆的高度&#xff0c;使车身更接近地面或提高离地间隙&#xff0c;从而改变车辆外观&#xff0c;增加个性化和独特性。 改善驾驶舒适性&#xff1a;空气悬挂系统具有更好的减震效果&#xff0c;可以提供更舒适的驾驶体验&#…

Ant design vue的表格双击编辑功能(即双击开始编辑并自动获得焦点,失去焦点时完成编辑)

本文基于Ant Design Vue官方网站的表格&#xff08;可编辑单元格&#xff09;&#xff08;表格 Table - Ant Design Vue (antdv.com))中的样板代码获得双击编辑且获得焦点、失去焦点时完成编辑的功能。 要点&#xff1a; &#xff08;1&#xff09;双击时候实现编辑&#xff…

docker同步bilibili收藏视频到群晖,可配合emby

作者是amtoaer&#xff0c;在github项目地址&#xff1a;https://github.com/amtoaer/bili-sync 有两个版本&#xff0c;1.0和2.0&#xff0c;我使用的是2.0 PS2&#xff1a;2.0和1.0版本目录结构不兼容&#xff0c;所以部署后会全量重新下载视频。 演示&#xff1a; 依然是…