IO技术详解

IO监控项在监控中一直是很重要的存在,服务有IO,磁盘有IO,操作系统也有IO,IO到底是什么呢

IO

IO,即“输入/输出”(Input/Output),是指计算机系统或设备之间交换数据的过程。这个概念在计算机科学、电子学和网络通信中应用广泛。IO 主要涉及两种操作:
输入 (Input):系统或设备接收的数据。例如,键盘输入的字符、网络接收的数据包,或磁盘读取的文件内容等。
输出 (Output):系统或设备输出的数据。例如,屏幕上显示的文本、网络发送的数据包,或写入磁盘的文件内容等。
​
IO 操作的目的通常是为了完成数据在不同组件或设备之间的传输和存储。它们通常有不同的表现形式,比如:
文件 IO:对文件的读写操作。
网络 IO:在网络连接中发送和接收数据。
设备 IO:对硬件设备(如硬盘、键盘、显示器等)进行的读写操作。
涉及计算机核心与其他设备间数据迁移的过程,就是IO。如磁盘IO,就是从磁盘读取数据到内存,这算一次输入,对应的,将内存中的数据写入磁盘,就算输出。
IO 操作可能受到硬件的物理限制,因而通常是系统性能的瓶颈之一
​
操作系统将内存空间分为用户空间和内核空间,用户空间是用户访问的内存区域,内核空间是操作系统访问的区域
我们的应用程序是跑在用户空间的,不存在实质的IO过程,真正的IO是在操作系统进行的
应用程序IO分为2部分,一是IO执行,操作系统执行,一是IO调用,应用调用操作系统的IO,

同步异步IO

同步 IO:在此下,程序会等待 IO 操作完成后再继续执行。这种方式比较简单,但可能导致程序因为等待 IO 而浪费大量时间。

异步 IO:程序在发起 IO 请求后无需等待 IO 完成,可以继续执行其他任务。IO 完成后,系统会通知程序,或让程序在空闲时自行检查 IO 状态。这种方式提高了系统资源利用率和并发性能。

在传统的同步IO模型中,程序会被某个IO操作阻塞,直到该操作完成后才会继续执行。而异步IO模型的核心思想是“不要等待”,即发起一个IO操作后,程序不会等待结果,而是通过事件通知或回调函数在IO操作完成后被告知结果。这样,程序在处理多个IO任务时就不会因为等待而卡住。

异步IO的实现方式

  1. 回调函数:在发起异步IO时,传入一个回调函数,在操作完成后执行该回调函数。这种方式在JavaScript中尤为常见,例如Node.js的事件驱动模型。

  2. Future/Promise:Future和Promise是异步编程中的抽象,用于存储异步操作的结果。通过检查Promise的状态,可以判断异步操作是否完成并获取结果。这种模式在Python、Java等语言中也得到了广泛应用。

  3. 事件循环(Event Loop):事件循环是实现异步IO的常用机制,程序运行在一个单线程上,由事件循环负责监控事件队列中的任务,依次处理完成的任务。例如,Node.js通过事件循环处理异步操作。

异步IO的优缺点

优点
  • 高效的资源利用:异步IO使程序不必等待IO操作的完成,从而充分利用CPU资源。

  • 高并发支持:适合处理大量并发请求,尤其在网络服务器、数据库等I/O密集型应用中。

缺点
  • 代码复杂度增加:引入了回调函数、事件循环等机制,程序逻辑会较同步模型复杂。

  • 调试难度增加:错误追踪和调试相对困难,尤其是在多层嵌套回调的情况下。

异步IO的应用场景

  • Web服务器:如Node.js,专为高并发和网络请求设计,擅长处理大量并发连接。

  • 数据库操作:异步IO可以减少数据库连接等待时间,提高查询性能。

  • 文件读写:尤其在文件传输、大规模文件处理场景中,通过异步处理文件读写,提升整体效率。

在Python中,可以使用asyncio库实现异步IO

import asyncio
​
async def fetch_data():
    print("Start fetching")
    await asyncio.sleep(2)  # 模拟IO操作
    print("Data fetched")
    return "data"
​
async def main():
    result = await fetch_data()
    print(result)
​
# 执行异步任务
asyncio.run(main())
​

fetch_data()是一个异步任务,通过await关键字实现非阻塞的IO操作

阻塞非阻塞IO

阻塞IO

在阻塞 IO 模式中,程序在发起 IO 操作后会被“阻塞”,即停止执行其他操作,直到 IO 操作完成。只有当数据完全读取或写入时,程序才会继续执行后续代码。内核数据没有准备好,用户进程则会一直等待,影响性能

特点
  • 简单易实现,常用于同步编程。

  • 程序会一直等待 IO 操作完成,导致 CPU 资源的利用率较低,可能造成性能瓶颈。

  • 适合对延迟要求不高的应用程序,或 IO 操作时间较短的场景。

# 阻塞 IO 示例
import socket
​
sock = socket.socket()
sock.connect(('example.com', 80))
sock.send(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
​
response = sock.recv(4096)  # 阻塞,等待接收数据
print(response)
sock.close()

非阻塞IO

在非阻塞 IO 模式中,程序发起 IO 操作后,不会等待 IO 操作完成,而是立即返回。程序可以继续执行其他任务,随时检查 IO 状态或等待系统通知 IO 操作的完成。

特点
  • 更高效,适合并发处理和多任务的场景。

  • 常与轮询(不断检查 IO 状态)或事件通知机制结合使用,比如 select()poll()epoll() 等。

  • 实现稍复杂,但能有效避免因等待 IO 而浪费 CPU 资源。

# 非阻塞 IO 示例
import socket
​
sock = socket.socket()
sock.setblocking(False)  # 设置为非阻塞模式
​
try:
    sock.connect(('example.com', 80))  # 发起连接
except BlockingIOError:
    # 非阻塞模式下立即返回,跳过阻塞状态
    pass
​
# 继续做其他事情
# 稍后再检查连接是否成功或有数据返回

IO多路复用

但是无效的轮询也会加大内存的开销

IO 多路复用是一种高效的 IO 模型,允许一个线程同时监视多个 IO 操作。它的核心思想是让操作系统帮助检测哪些 IO 资源已经准备好进行读写,而不是让每个 IO 操作都单独等待。这样可以有效地提高系统资源利用率,尤其适合处理大量并发连接的场景,如网络服务器。

在 IO 多路复用中,常用的系统调用包括 selectpollepoll

常用的 IO 多路复用方法

  1. select

    • select 是最早实现 IO 多路复用的系统调用,通过一个文件描述符集合来监控多个 IO 通道。

    • 它的调用会阻塞进程,直到一个或多个文件描述符变为就绪(可读、可写或有异常发生),然后程序可以对就绪的文件描述符执行 IO 操作。

    • 缺点在于文件描述符集合的大小有限,且需要遍历所有的文件描述符,性能较低。

  2. poll

    • pollselect 的改进版,没有文件描述符数量限制,解决了 select 的一些不足。

    • poll 通过一个数组而非集合来管理文件描述符,但仍然需要轮询所有文件描述符,且每次调用都需要重新构建文件描述符数组。

    • 随着文件描述符数量增加,poll 的性能会下降。

  3. epoll

    • epoll 是 Linux 下的高效 IO 多路复用方式,针对 selectpoll 的性能问题进行了优化。

    • epoll 的文件描述符不需要重复传递,且支持“边缘触发(edge-triggered)”和“水平触发(level-triggered)”两种模式,能够更高效地检测文件描述符的状态变化。

    • 它适合处理大量并发连接,被广泛用于高并发服务器(如 Nginx、Redis)中。

IO 多路复用的工作流程

  1. 程序创建并注册多个 IO 事件(文件描述符),告诉操作系统哪些事件需要监控。

  2. 操作系统负责检测文件描述符的状态变化,直到某些 IO 事件就绪,然后通知程序。

  3. 程序收到通知后,仅对就绪的 IO 事件执行读写操作,避免了阻塞等待,从而实现高效处理。

IO 多路复用的优势

  • 高效性:程序无需轮询所有 IO 操作,而是让操作系统通知哪些 IO 就绪,避免了不必要的 CPU 消耗。

  • 支持并发:一个线程可监控多个 IO 操作,适合高并发应用场景,避免了线程或进程创建的资源开销。

  • 提高资源利用率:通过集中管理 IO 操作,可以大幅减少阻塞时间,让程序高效利用 CPU。

import select
import socket
​
# 创建两个监听 socket
sock1 = socket.socket()
sock1.bind(('0.0.0.0', 8000))
sock1.listen()
​
sock2 = socket.socket()
sock2.bind(('0.0.0.0', 8001))
sock2.listen()
​
# 把 socket 放入 select 监控列表
inputs = [sock1, sock2]
outputs = []
​
while True:
    # 调用 select,监控 inputs 列表中的 socket 是否有数据就绪
    readable, writable, exceptional = select.select(inputs, outputs, inputs)
​
    for s in readable:
        if s is sock1 or s is sock2:
            # 有新的连接请求
            conn, addr = s.accept()
            print(f"Connection from {addr}")
            inputs.append(conn)
        else:
            # 处理现有连接的数据
            data = s.recv(1024)
            if data:
                print("Received:", data.decode())
                s.send(b"Echo: " + data)
            else:
                # 连接关闭
                print("Closing connection")
                inputs.remove(s)
                s.close()

在这个例子中,select.select() 会阻塞进程,直到有 IO 事件发生。通过这种方式,可以用一个线程或进程处理多个客户端连接,从而有效利用资源。

IO模型

阻塞IO同步阻塞
非阻塞IO同步非阻塞
IO多路复用同步阻塞
异步IO异步非阻塞

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

指令存储和指令流水线

要求存储器的编址单位,首先观察到计算机采用的是32位定长指令字,因此一条指令就是32位,即4B,根据表中可知一条指令所占地址空间为08048104H-08048100H4H,因此所用的编制单位为字节(B) 将所有指令…

kafka管理工具

文章目录 前言一、Kafka Assistan1.1 描述1.2、配置安装 二、Conduktor2.1、描述2.2、配置安装 三、kafka-maneger3.1、描述3.2、配置安装3.3、命令启动3.4、[refer to](https://www.ctyun.cn/document/10000120/10033218#section-39755766f4910e4b) 前言 提示:这里…

JavaWeb常见注解

1.Controller 在 JavaWeb 开发中,Controller是 Spring 框架中的一个注解,主要用于定义控制器类(Controller),是 Spring MVC 模式的核心组件之一。它表示该类是一个 Spring MVC 控制器,用来处理 HTTP 请求并…

axios平替!用浏览器自带的fetch处理AJAX(兼容表单/JSON/文件上传)

fetch 是啥? fetch 函数是 JavaScript 中用于发送网络请求的内置 API,可以替代传统的 XMLHttpRequest。它可以发送 HTTP 请求(如 GET、POST 等),并返回一个 Promise,从而简化异步操作 基本用法 /* 下面是…

window任务计划记录中显示操作成功,但是代码只执行了第一句命令

一、创建定时任务 1. Windows键R 调出此窗口,输入compmgmt.msc (调用的是计算机管理) 2. 创建基本任务 在任务计划程序中右键 选择 创建基本任务。 输入任务名称及描述。 下一步中选择触发器的时间,这里选择每天。 选择开始时间&…

使用VSCode远程连接服务器并解决Neo4j无法登陆问题

摘要:本文介绍了如何通过VSCode连接内网部署的Neo4j服务器,并启动服务。在访问Neo4j登录界面时,遇到了端口映射问题导致无法登录。通过手动添加7687端口的映射后,成功登录Neo4j。 我在内网部署了一台服务器,并在其上运…

【异常解决】Linux shell报错:-bash: [: ==: 期待一元表达式 解决方法

博主介绍:✌全网粉丝21W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

游戏引擎学习第四天

视频参考:https://www.bilibili.com/video/BV1aDmqYnEnc/ BitBlt 是 Windows GDI(图形设备接口)中的一个函数,用于在设备上下文(device context, DC)之间复制位图数据。BitBlt 的主要用途是将一个图像区域从一个地方复…

七牛云上传图片成功,但是无法访问显示{error : document not found}

上传图片成功,但是访问不了的问题,直接把地址放进浏览器显示{error : document not found},直接访问 DCNF 404是符合预期的,因为还没有去空间复制外链,要访问实际存在的资源才可以的. 配置区域和访问域名 设置没问题了…

通过投毒Bingbot索引挖掘必应中的存储型XSS

简介 在本文中,我将讨论如何通过从外部网站对Bingbot进行投毒,来在Bing.com上实现持久性XSS攻击。 什么是存储型或持久性XSS?存储型攻击指的是将恶意脚本永久存储在目标服务器上,例如数据库、论坛、访问日志、评论栏等。受害者在…

84.7k Star!Excalidraw:开源的在线白板工具,具备手绘风格和实时协作功能

❤️ 如果你也关注大模型与 AI 的发展现状,且对大模型应用开发非常感兴趣,我会快速跟你分享最新的感兴趣的 AI 应用和热点信息,也会不定期分享自己的想法和开源实例,欢迎关注我哦! 🥦 微信公众号&#xff…

让Git走代理

有时候idea提交代码或者从github拉取代码,一直报错超时或者:Recv failure: Connection was reset,下面记录一下怎么让git走代理从而访问到github。 1.打开梯子 2.打开网络和Internet设置 3.设置代理 记住这个地址和端口 4.打开git bash终端 输入以下内容 git c…

CSS:导航栏三角箭头

用CSS实现导航流程图的样式。可根据自己的需求进行修改,代码精略的写了一下。 注:场景一和场景二在分辨率比较低的情况下会有一个1px的缝隙不太优雅,自行处理。有个方法是直接在每个外面包一个DIV,用动态样式设置底色。 场景一、…

第4章-计划 4.3 订计划、勤跟踪、要闭环

4.3 订计划、勤跟踪、要闭环 1.制订好的第一版计划先要基线化,确保有据可依2.计划要监督执行,发现延期时要“喊出来”3.计划要赶得上变化4.资源保障是计划能够执行的依赖 坚定执行制订好的计划,监督执行效果,计划产生偏差时及时制…

在 WPF 中,如何实现数据的双向绑定?

在 WPF 中,数据绑定是一个非常重要的特性,它允许 UI 与数据源之间自动同步。双向绑定是一种常见的绑定方式,当数据源更新时,UI 会自动更新;同样,当 UI 中的元素(如文本框)发生改变时…

Java面向对象编程进阶之包装类

Java面向对象编程进阶之包装类 一、为什么要使用包装类二、掌握基本数据类型与包装类之间的转换1、为什么需要转换?2、如何转换? 三、String与基本数据类型、包装类之间的转换1、案例2、特别注意 一、为什么要使用包装类 为了使得基本类型的数据变量具备…

基于Spring Boot与Redis的令牌主动失效机制实现

目录 前言1. 项目结构和依赖配置1.1 项目依赖配置1.2 Redis连接配置 2. 令牌主动失效机制的实现流程2.1 登录成功后将令牌存储到Redis中2.2 使用拦截器验证令牌2.3 用户修改密码后删除旧令牌 3. Redis的配置与测试4. 可能的扩展与优化结语 前言 在现代Web系统中,用…

yolov8-cls的onnx与tensorrt推理

本文不生产技术,只做技术的搬运工! 前言 最近需要使用yolov8-cls进行模型分类任务,但是使用ultralytics框架去部署非常不方便,因此打算进行onnx或者tensorrt去部署,查看了很多网上的帖子,并没有发现有完整复现yolov8-cls前处理(不需要后处理)的"轮子",通过自己debug…

Acrobat Pro DC 2023(pdf免费转化word)

所在位置 通过网盘分享的文件:Acrobat Pro DC 2023(64bit).tar 链接: https://pan.baidu.com/s/1_m8TT1rHTtp5YnU8F0QGXQ 提取码: 1234 --来自百度网盘超级会员v4的分享 安装流程 打开安装所在位置 进入安装程序 找到安装程序 进入后点击自定义安装,这里…

VMware和CentOS 7.6 Linux操作系统的安装使用

1. 安装VMware 安装VMware之前,有些电脑是需要去BIOS里修改设置开启cpu虚拟化设备支持才能安装。如果运气不好在安装过程中安装不了的话就自行百度吧。 打开 VMware 的官网: https://www.vmware.com/ 点击 product,往下滑找到 see desktop hypeerviso…