IO概念

article/2025/4/26 21:50:55

IO概念和五种IO模型

一、什么是IO?

我们都知道unix世界里、一切皆文件、而文件是什么呢?文件就是一串二进制流而已、不管socket、还是FIFO、管道、终端、对我们来说、一切都是文件、一切都是流、在信息交换的过程中、我们都是对这些流进行数据的收发操作、简称为I/O操作(input and output)、往流中读出数据、系统调用read、写入数据、系统调用write、不过话说回来了、计算机里有这么多的流、我怎么知道要操作哪个流呢?做到这个的就是文件描述符、即通常所说的fd、一个fd就是一个整数、所以对这个整数的操作、就是对这个文件(流)的操作、我们创建一个socket、通过系统调用会返回一个文件描述符、那么剩下对socket的操作就会转化为对这个描述符的操作、不能不说这又是一种分层和抽象的思想、

在这里插入图片描述

二、IO交互
通常用户进程中的一个完整IO分为两阶段:
用户空间 <-----> 内核空间、
内核空间 <-----> 设备空间、

在这里插入图片描述

内核空间中存放的是内核代码和数据、而进程的用户空间中存放的是用户程序的代码和数据、不管是内核空间还是用户空间、它们都处于虚拟空间中、Linux使用两级保护机制:0级供内核使用、3级供用户程序使用、

操作系统和驱动程序运行在内核空间、应用程序运行在用户空间、两者不能简单地使用指针传递数据、因为Linux使用的虚拟内存机制、其必须通过系统调用请求kernel来协助完成IO动作、内核会为每个IO设备维护一个缓冲区、用户空间的数据可能被换出、当内核空间使用用户空间指针时、对应的数据可能不在内存中

对于一个输入操作来说、进程IO系统调用后、内核会先看缓冲区中有没有相应的缓存数据、没有的话再到设备中读取、因为设备IO一般速度较慢、需要等待、内核缓冲区有数据则直接复制到进程空间、

所以、对于一个网络输入操作通常包括两个不同阶段:

(1)等待网络数据到达网卡 –> 读取到内核缓冲区

(2)从内核缓冲区复制数据 –> 用户空间

IO有内存IO

网络IO

磁盘IO三种、通常我们说的IO指的是后两者

三、POSIX

对IO底层交互感兴趣的小伙伴可以好好了解一下POSIX(Portable Operating System Interface for Computing System)、我对深沉次原理也不怎么熟、之所以写此篇博文也是为了后面的Java IO学习、深入浅出点到即可、此章节给有兴趣的朋友一个引子、

四、IO模型

《UNIX网络编程》说得很清楚、5种IO模型分别是阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动的IO模型、异步IO模型、前4种为同步IO操作、只有异步IO模型是异步IO操作、请仔细阅读IO交互便于理解IO模型
在这里插入图片描述

(一)阻塞IO模型

当用户进程调用了recvfrom这个系统调用、内核就开始了IO的第一个阶段:准备数据、对于网络IO来说、很多时候数据在一开始还没有到达(比如、还没有收到一个完整的UDP包)、这个时候内核就要等待足够的数据到来、而在用户进程这边、整个进程会被阻塞、当内核一直等到数据准备好了、它就会将数据从内核中拷贝到用户内存、然后返回结果、用户进程才解除阻塞的状态、重新运行起来、几乎所有的程序员第一次接触到的网络编程都是从listen()、send()、recv()等接口开始的、这些接口都是阻塞型的、

blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被阻塞了、

典型应用:阻塞Socket、Java BIO

进程阻塞挂起不消耗CPU资源、及时响应每个操作

实现难度低、开发应用较容易

适用并发量小的网络应用开发

不适用并发量大的应用、因为一个请求IO会阻塞进程、所以、得为每请求分配一个处理进程(线程)以及时响应、系统开销大

(二)非阻塞IO模型

当用户进程发出read操作时、如果内核中的数据还没有准备好、那么它并不会block用户进程、而是立刻返回一个error、从用户进程角度讲、它发起一个read操作后、并不需要等待、而是马上就得到了一个结果、用户进程判断结果是一个error时、它就知道数据还没有准备好、于是它可以再次发送read操作、一旦内核中的数据准备好了、并且又再次收到了用户进程的系统调用、那么它马上就将数据拷贝到了用户内存、然后返回、非阻塞的接口相比于阻塞型接口的显著差异在于、在被调用之后立即返回、

在非阻塞式IO中、用户进程其实是需要不断的主动询问kernel数据准备好了没有

典型应用:Socket 设置 NONBLOCK

进程轮询(重复)调用、消耗CPU的资源

实现难度低、开发应用相对阻塞IO模式较难

适用并发量较小、且不需要及时响应的网络应用开发

在这里插入图片描述

(三)IO复用模型

多个的进程的IO可以注册到一个复用器(select)上、当用户进程调用该select、select会监听所有注册进来的IO、如果select所有监听的IO在内核缓冲区都没有可读数据、select调用进程会被阻塞、而当任一IO在内核缓冲区中有可数据时、select调用就会返回、而后select调用进程可以自己或通知另外的进程(注册进程)来再次发起读取IO、读取内核中准备好的数据、多个进程注册IO后、只有一个select调用进程被阻塞

IO复用相对阻塞和非阻塞更难简单说明、所以额外解释一段、其实IO复用模型和阻塞IO模型并没有太大的不同、事实上、还更差一些、因为这里需要使用两个系统调用(select和 recvfrom)、而阻塞IO模型只有一次系统调用(recvfrom)、但是、用select的优势在于它可以同时处理多个连接、所以如果处理的连接数不是很高的话、使用select/epoll的web server不一定比使用多线程加阻塞IO的web server性能更好、可能延迟还更大、select/epoll的优势并不是对于单个连接能处理得更快、而是在于能处理更多的连接

在IO复用模型中、对于每一个socket、一般都设置成为非阻塞、但是、如上图所示、整个用户的进程其实是一直被阻塞的、只不过进程是被select这个函数阻塞、而不是被socket IO给阻塞

典型应用:Java NIO、Nginx(epoll、poll、select)

专一进程解决多个进程IO的阻塞问题、性能好、Reactor模式

实现、开发应用难度较大

适用高并发服务应用开发、一个进程/线程响应多个请求

在这里插入图片描述

(四)信号驱动式IO模型

信号驱动式IO就是指进程预先告知内核、向内核注册一个信号处理函数、然后用户进程返回不阻塞、当内核数据就绪时会发送一个信号给进程、用户进程便在信号处理函数中调用IO读取数据、从图中明白实际IO内核拷贝到用户进程的过程还是阻塞的、信号驱动式IO并没有实现真正的异步、因为通知到进程之后、依然是由进程来完成IO操作、

这和后面的异步IO模型很容易混淆、需要理解IO交互并结合五种IO模型的比较阅读

在信号驱动式IO模型中、依然不符合POSIX描述的异步IO、只能算是半异步、并且实际中并不常用、

典型应用:(不知道)

回调机制、实现、开发应用难度大

在这里插入图片描述

(5)异步IO模型

用户进程发起aio_read(POSIX异步IO函数aio_或者lio_开头)操作之后、给内核传递描述符、缓冲区指针、缓冲区大小和read相同的三个参数以及文件偏移(与lseek类似)、告诉内核当整个操作完成时、如何通知我们、立刻就可以开始去做其它的事、而另一方面、从内核的角度、当它受到一个aio_read之后、首先它会立刻返回、所以不会对用户进程产生任何阻塞、然后、内核会等待数据准备完成、然后将数据拷贝到用户内存、当这一切都完成之后、内核会给用户进程发送一个信号、告诉它aio_read操作完成了

异步IO的工作机制是:告知内核启动某个操作、并让内核在整个操作完成后通知我们、这种模型与信号驱动的IO区别在于、信号驱动IO是由内核通知我们何时可以启动一个IO操作、这个IO操作由用户自定义的信号函数来实现、而异步IO模型是由内核告知我们IO操作何时完成、

这和前面的信号驱动式IO模型很容易混淆、需要理解IO交互并结合五种IO模型的比较阅读

在异步IO模型中、真正实现了POSIX描述的异步IO、是五种IO模型中唯一的异步模型

典型应用:Java 7 AIO、高性能服务器应用

不阻塞、数据一步到位、Proactor模式

需要操作系统的底层支持、LINUX 2.5 版本内核首现、2.6 版本产品的内核标准特性

回调机制、实现、开发应用难度大

非常适合高性能高并发应用

(六)五种IO模型的比较

阻塞IO和非阻塞IO的区别在哪?

前面的介绍中其实已经很明确的说明了这两者的区别、调用阻塞会一直阻塞住对应的进程直到操作完成、而非阻塞IO在内核还没准备数据的情况下会立刻返回、阻塞和非阻塞关注的是进程在等待调用结果时的状态、阻塞是指调用结果返回之前、当前进程会被挂起、调用进程只有在得到结果才会返回、非阻塞调用指不能立刻得到结果、该调用不会阻塞当前进程、

同步IO和异步IO区别在哪?

两者的区别就在于同步做IO操作的时候会将进程阻塞、按照这个定义、之前所述的阻塞IO、非阻塞IO、IO复用、信号驱动都属于同步IO、有人可能会说、非阻塞IO并没有被阻塞啊、这里有个非常狡猾的地方、定义中所指的IO操作是指真实的IO操作、就是例子中的recvfrom这个系统调用、非阻塞IO在执行recvfrom这个系统调用的时候、如果内核的数据没有准备好、这时候不会阻塞进程、但是、当内核中数据准备好的时候、recvfrom会将数据从内核拷贝到用户内存中、这个时候进程是被阻塞了、信号驱动也是同样的道理、在这段时间内、进程是被阻塞的、而异步IO则不一样、当进程发起IO操作之后、就直接返回再也不理睬了、直到内核发送一个信号、告诉进程说IO完成、在这整个过程中、进程完全没有被阻塞、

同异步IO的根本区别在于、同步IO主动的调用recvfrom来将数据拷贝到用户内存、而异步则完全不同、它就像是用户进程将整个IO操作交给了他人(内核)完成、然后他人做完后发信号通知、在此期间、用户进程不需要去检查IO操作的状态、也不需要主动的去拷贝数据

信号驱动式IO和异步IO的区别?

这里之所以单独拿出来是因为如果还没有清除IO概念很容易混淆、所以理解IO模型之前一定要理解IO概念、如果看完前面两个问题、相信也能理解信号驱动IO与异步IO的区别在于启用异步IO意味着通知内核启动某个IO操作、并让内核在整个操作(包括数据从内核复制到用户缓冲区)完成时通知我们、也就是说、异步IO是由内核通知我们IO操作何时完成、即实际的IO操作也是异步的、信号驱动IO是由内核通知我们何时可以启动一个IO操作、这个IO操作由用户自定义的信号函数来实现


http://chatgpt.dhexx.cn/article/acVgLjGa.shtml

相关文章

顺序IO和随机IO

顺序IO和随机IO 什么是顺序IO和随机IO如何解决随机IO造成的性能损失&#xff1f;问题什么是IOPS?机械硬盘和固态硬盘在随机IO上性能的影响因素&#xff1f;SSD作为随机存储设备&#xff0c;其访问任意一块的时间应该是相等的&#xff0c;为什么顺序IO还是快于随机IO? 什么是顺…

绘图工具-draw.io

draw.io是一个可配置的图表/白板可视化应用程序。draw.io 由英国软件公司JGraph Ltd拥有和开发。这是一个开源项目&#xff08;但对贡献是封闭的&#xff09;&#xff0c;github链接&#xff1a;https://github.com/jgraph&#xff0c;可以绘制流程图、UML、类图、组织结构图、…

什么是IO Pad?

1.什么是IO pad&#xff1f; IO pad是一个芯片管脚处理模块&#xff0c;即可以将芯片管脚的信号经过处理送给芯片内部&#xff0c;又可以将芯片内部输出的信号经过处理送到芯片管脚。输入信号处理包含时钟信号&#xff0c;复位信号等&#xff0c;输出信号包含观察时钟、中断等…

Drawio使用简介(慢慢更新中)

drawio是一款强大、免费的绘图工具&#xff08;基本可以替代收费的visio等&#xff09;&#xff0c;使用起来非常方便。支持网页版使用&#xff08;网页版可以自己部署一套&#xff09;以及客户端使用&#xff08;支持windows&#xff0c;MacOS以及Linux&#xff09;。 该项目…

计算机io接口主要功能,io接口的功能是什么

IO接口又称为输入输出接口,是信息处理系统与外部世界之间的通信。输入是系统接收的信号或数据,输出是从其发送的信号或数据。该术语也可以用作行动的一部分; 到“执行I / O”是执行输入或输出操作。 IO 接口,又称为输入输出接口,是信息处理系统(例如计算机)与外部世界(可能是人…

到底什么是IO

IO 作为操作系统的核心知识之一, 无论是在本机、传统的单体应用、还是分布式系统中,都有非常重要的地位. 今天就和大家系统地聊一聊 IO 相关的东西. IO IO&#xff0c;Input/Output 简写&#xff0c;是指内存和外设之间的数据复制的过程. 输入是指数据从外设复制到内存中, 输…

一文掌握 IO 基础知识与概念

&#x1f49e;哈喽&#xff01;大家好&#xff0c;我是HappyGirl快乐女孩&#x1f49e; &#x1f61c;是一位爱好技术的【技术Fans】&#xff01;&#x1f61c; &#x1f49e;&#x1f49e;&#x1f49e; 如果有对技术感兴趣的宅友&#xff0c;欢迎关注&#x1f49e;&#x1f4…

韦东山freeRTOS系列教程之【第三章】任务管理

文章目录 系列教程总目录概述3.1 基本概念3.2 任务创建与删除3.2.1 什么是任务3.2.2 创建任务3.2.3 示例1: 创建任务3.2.4 示例2: 使用任务参数3.2.5 任务的删除3.2.6 示例3: 删除任务 3.3 任务优先级和Tick3.3.1 任务优先级3.3.2 Tick3.3.3 示例4: 优先级实验3.3.4 示例5: 修改…

FreeRTOS教程——定时器(二)

Free RTOS定时器 一、概念 一、概论 软件定时器允许设置一段时间&#xff0c;当设置的时间到达之后就执行指定的功能函数&#xff0c;被定时器 调用的这个功能函数叫做定时器的回调函数。回调函数的两次执行间隔叫做定时器的定时周期&#xff0c; 简而言之&#xff0c;当定时…

韦东山freeRTOS系列教程之【第二章】内存管理

文章目录 教程目录2.1 为什么要自己实现内存管理2.2 FreeRTOS的5种内存管理方法2.2.1 Heap_12.2.2 Heap_22.2.3 Heap_32.2.4 Heap_42.2.5 Heap_5 2.3 Heap相关的函数2.3.1 pvPortMalloc/vPortFree2.3.2 xPortGetFreeHeapSize2.3.3 xPortGetMinimumEverFreeHeapSize2.3.4 malloc…

FreeRTOS学习记录(安富莱FreeRTOS教程摘录)

FreeRTOS学习资料&#xff1a; 安富莱论坛FreeRTOS教程 FreeRTOS源码下载链接 第1章 为什么选用FreeRTOS 1.1 FreeRTOS优势 FreeRTOS优势 最大的优势就是开源免费&#xff0c;商业使用的话不需要用户公开源代码&#xff0c;也不存在任何版权问题&#xff0c;是当前小型嵌入…

STM32 FreeRTOS系列教程(一)FreeRTOS简介

参考资料&#xff1a;《正点原子STM32F4 FreeRTOS开发手册_V1.1》《野火FreeRTOS 内核实现与应用开发实战—基于STM32》 学习RTOS的意义 当我们进入嵌入式这个领域的时候&#xff0c;往往首先接触的都是单片机编程&#xff0c;单片机编程又 首选51 单片机来入门。这里面说的单…

FreeRTOS使用教程(配合CubeMX)

FreeRTOS使用教程&#xff08;配合CubeMX&#xff09; 一、CubeMX配置 在选择后单片机芯片后&#xff0c;在Middleware中选择FREERTOS的CMSIS_V1版本即可在工程开启FreeRTOS。 关于FreeRTOS的具体配置一般集中在Kernel Setting中。具体参数一般可以默认&#xff0c;有特殊需求…

【STM32】STM32CubeMX使用FreeRTOS教程1----定时器学习

【STM32】STM32CubeMX使用FreeRTOS教程1----定时器学习 前言 本教程将对应外设原理&#xff0c;HAL库、STM32CubeMX和FreeRTOS结合在一起讲解&#xff0c;分析学习过程中遇到的问题和一些注意事项。 知识概括&#xff1a; SMT32定时器原理 STM32CubeMX创建定时器例程 HAL库…

[FreeRTOS系列教程]学习FreeRTOS前的准备工作-----初学者必看

转自&#xff1a;http://bbs.armfly.com/read.php?tid1552 转载说明&#xff1a;本文仅为转载&#xff0c;下面有几位同学询问对应的教程&#xff0c;教程请参考下面的链接&#xff0c;是以帖子的形式分章节说明。 http://bbs.armfly.com/thread.php?fid14&type29&…

FreeRTOS基本教程零:STM32 FReeRTOS 移植流程

一、资料准备 FreeRTOS源码下载地址&#xff1a; https://github.com/FreeRTOS/FreeRTOShttps://github.com/FreeRTOS/FreeRTOS我移植的是FreeRTOSv9.0.0 stm32裸机程序&#xff1a; 二、FreeRTOS目录 一共有三个文件夹 其中Demo文件夹中是FreeRTOS的例程&#xff0c;Licen…

基于STM32的实时操作系统FreeRTOS移植教程(手动移植)

前言&#xff1a;此文为笔者FreeRTOS专栏下的第一篇基础性教学文章&#xff0c;其主要目的为&#xff1a;帮助读者朋友快速搭建出属于自己的公版FreeRTOS系统&#xff0c;实现后续在实时操作系统FreeRTOS上的开发与运用。操作系统的学习与运用可以说是每位嵌入式开发工程师必须…

STM32F103--移植FreeRTOS完整教程

最近按照正点原子教程开始学习FreeRTOS&#xff0c;发现其手册的移植教程中有些地方可能不是那么详细&#xff0c;在此基于正点原子做一期最完整的FreeRTOS移植教程给大家。 小b将本次教程整理的资料放在网盘&#xff0c;以下链接供各位小伙伴下载和学习&#xff1a; 链接&…

FreeRTOS 正点原子教程学习笔记

正点原子视频教程 FreeRTOS(教程非常详细&#xff09; 小知识 如果创建了任务却完全空着&#xff0c;没有while&#xff08;1&#xff09;{延时}的话&#xff0c;整个程序会卡住&#xff0c;其他正常的任务无法运行。如果任务里单单有赋值之类的操作也会卡死在这个任务&#…

FreeRTOS入门教程(堆和栈)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、FreeRTOS操作系统介绍二、堆1.概念介绍2.简单实现 三、栈总结 前言 本篇文章正式学习FreeRTOS操作系统&#xff0c;我打算编写一系列文章带大家轻松快速入…