五种IO模型- 阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO
在操作系统中处理输入/输出(IO)操作的过程中,存在多种方式,包括阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。这些方式在操作系统实现和应用程序编写时有着不同的适用场景和性能特征。接下来,我将逐一介绍它们的实现原理、优缺点以及应用场景,同时给出Java和Python的实验示例。
1. 阻塞IO (Blocking IO)
实现原理:
在阻塞IO中,IO操作会导致应用程序被阻塞,直到IO操作完成。这意味着,应用程序在发出IO请求后,需要等到数据完全准备好或者已经被发送完成后才能继续执行其他操作。
优缺点:
- 优点:实现简单,程序逻辑容易理解。
- 缺点:效率低下,因为线程会在IO操作上等待,从而阻塞程序处理其他任务。
应用场景:
适用于简单的、并发性要求不高的场景,如命令行工具、简单的文件读写操作。
Java实验示例:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;public class BlockingIOExample {public static void main(String[] args) throws IOException {Socket socket = new Socket("example.com", 80);BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line;// This read operation will block until data is availablewhile ((line = reader.readLine()) != null) {System.out.println(line);}}
}
Python实验示例:
import socketdef blocking_io_example():s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(("example.com", 80))s.sendall(b"GET / HTTP/1.0\r\n\r\n")data = s.recv(1024) # This will blockwhile data:print(data.decode())data = s.recv(1024) # This will block againblocking_io_example()
2. 非阻塞IO (Non-blocking IO)
实现原理:
在非阻塞IO中,应用程序在发出IO请求时,如果数据不立即可用,则立即返回而不是阻塞。这可以通过不停地轮询IO设备来检查数据可用性。
优缺点:
- 优点:不需要等待IO操作结束,可以进行其他处理,较少IO等待时间。
- 缺点:可能会导致CPU空转浪费资源,需要通过轮询检查数据可用性。
应用场景:
适合需要快速反应和并发处理的网络服务或GUI应用程序。
Java实验示例:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.net.InetSocketAddress;public class NonBlockingIOExample {public static void main(String[] args) throws IOException {SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress("example.com", 80));while (!socketChannel.finishConnect()) {// Busy-wait, can perform other tasks}ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = socketChannel.read(buffer); // Non-blocking readwhile (bytesRead != -1) {buffer.flip();while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}buffer.clear();bytesRead = socketChannel.read(buffer); // Non-blocking read}}
}
Python实验示例:
import socket
import selectorsdef non_blocking_io_example():s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.setblocking(False)s.connect_ex(("example.com", 80))selector = selectors.DefaultSelector()selector.register(s, selectors.EVENT_WRITE)while True:for key, events in selector.select():sock = key.fileobjif events & selectors.EVENT_WRITE:sock.sendall(b"GET / HTTP/1.0\r\n\r\n")selector.unregister(sock)selector.register(sock, selectors.EVENT_READ)elif events & selectors.EVENT_READ:data = sock.recv(1024)if data:print(data.decode())else:returnnon_blocking_io_example()
3. 多路复用IO (IO Multiplexing)
实现原理:
多路复用IO采用一个或者多个IO接口来监控多个文件描述符,一旦某个文件描述符就绪,应用程序就会得到通知。这可以通过select
、poll
、epoll
等系统调用实现。
优缺点:
- 优点:高效地处理多个IO通道,适合高并发场景。
- 缺点:代码复杂度较高,底层实现与具体平台绑定,可能在短期大量连接时性能下降。
应用场景:
适用于高并发服务器,如Web服务器、聊天服务器。
Java实验示例:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;public class MultiplexingIOExample {public static void main(String[] args) throws IOException {Selector selector = Selector.open();SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress("example.com", 80));socketChannel.register(selector, SelectionKey.OP_CONNECT);while (true) {selector.select();Iterator<SelectionKey> keys = selector.selectedKeys().iterator();while (keys.hasNext()) {SelectionKey key = keys.next();keys.remove();if (key.isConnectable()) {SocketChannel sc = (SocketChannel) key.channel();if (sc.finishConnect()) {sc.register(selector, SelectionKey.OP_READ);}} else if (key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int bytesRead = sc.read(buffer);if (bytesRead > 0) {buffer.flip();while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}} else if (bytesRead == -1) {sc.close();}}}}}
}
Python实验示例:
import socket
import selectorsdef multiplexing_io_example():selector = selectors.DefaultSelector()s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.setblocking(False)s.connect_ex(("example.com", 80))selector.register(s, selectors.EVENT_WRITE)while True:events = selector.select()for key, event in events:sock = key.fileobjif event & selectors.EVENT_WRITE:sock.sendall(b"GET / HTTP/1.0\r\n\r\n")selector.modify(sock, selectors.EVENT_READ)elif event & selectors.EVENT_READ:data = sock.recv(1024)if data:print(data.decode())else:selector.unregister(sock)sock.close()returnmultiplexing_io_example()
4. 信号驱动IO (Signal-driven IO)
实现原理:
信号驱动IO主要依赖于信号机制,应用程序可以为某个文件描述符设置某种IO事件的信号处理函数。当事件发生时,内核会通知应用程序。
优缺点:
- 优点:减少轮询开销,与异步IO结合时可以实现更高效的非阻塞操作。
- 缺点:编程复杂度较高,各平台对信号处理支持不一致,信号过多可能影响性能。
应用场景:
适合轻量级IO处理或当频繁通知不成问题时,如消息通知系统。
由于信号驱动IO在Java和Python中实现较为复杂且依赖于底层操作系统特性,因此在这里不提供具体的实验示例。
5. 异步IO (Asynchronous IO)
实现原理:
在异步IO中,应用程序只需发起IO操作,内核负责完成操作并在操作结束后通知应用程序。应用程序在IO操作过程中可以继续执行其他任务,并且不需要等待。
优缺点:
- 优点:效率高,是实现高并发和低延迟的理想方式,通过事件机制可以减少开销。
- 缺点:编程模型和调试复杂,错误处理较为困难。
应用场景:
适用于高性能、高并发服务器,如现代Web服务器、异步网络操作、I/O密集型应用。
Java实验示例 NIO2
from Java 7:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutionException;public class AsynchronousIOExample {public static void main(String[] args) {try {AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open();socketChannel.connect(new InetSocketAddress("example.com", 80)).get();ByteBuffer buffer = ByteBuffer.allocate(1024);socketChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer buffer) {buffer.flip();while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}}@Overridepublic void failed(Throwable exc, ByteBuffer buffer) {System.out.println("Failed: " + exc.getMessage());}});} catch (IOException | InterruptedException | ExecutionException e) {e.printStackTrace();}}
}
Python实验示例:
import asyncioasync def async_io_example():reader, writer = await asyncio.open_connection('example.com', 80)writer.write(b"GET / HTTP/1.0\r\n\r\n")await writer.drain()while True:data = await reader.read(1024)if data:print(data.decode())else:breakasyncio.run(async_io_example())
总结不同IO模型的选择,应依赖于具体需求和环境。阻塞IO适合简单任务;非阻塞和多路复用IO适应高并发;信号驱动IO用于轻量级通知场景;而异步IO则用于高性能应用。
相关文章:
五种IO模型- 阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO
在操作系统中处理输入/输出(IO)操作的过程中,存在多种方式,包括阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。这些方式在操作系统实现和应用程序编写时有着不同的适用场景和性能特征。接下来,我将逐一介绍它们…...
Vscode GStreamer插件开发环境配置
概述 本教程使用vscode和Docker搭建Gstreamer2.24的开发环境,可以用于开发调试Gstreamer程序或者自定义插件开发。 1. vscode依赖插件 C/C Extension Pack(ms-vscode.cpptools-extension-pack):该插件包包含一组用于 Visual St…...

flask基础
from flask import Flask, requestapp Flask(__name__)# app.route(/) # def hello_world(): # put applications code here # return Hello World!app.route(/) # 路由 当用户访问特定 URL 时,Flask 会调用对应的视图函数来处理请求 def index():return …...

Java日志框架:log4j、log4j2、logback
文章目录 配置文件相关1. properties测试 2. XMl使用Dom4j解析XML Log4j与Log4j2日志门面 一、Log4j1.1 Logges1.2 Appenders1.3 Layouts1.4 使用1.5 配置文件详解1.5.1 配置根目录1.5.2 配置日志信息输出目的地Appender1.5.3 输出格式设置 二、Log4j22.1 XML配置文件解析2.2 使…...

鸿蒙-expandSafeArea使用
应用未使用setWindowLayoutFullScreen()接口设置窗口全屏布局时,默认使能组件安全区布局。可以使用expandSafeArea属性扩展安全区域属性进行调整 扩展安全区域属性原理 布局阶段按照安全区范围大小进行UI元素布局。布局完成后查看设置了expandSafeArea的组件边界&…...
【es6复习笔记】Spread 扩展运算符(8)
在现代前端开发中,JavaScript 的扩展运算符(Spread Operator)是一个非常有用的特性,它允许你将数组或对象展开,以便在函数调用、数组拼接、对象复制等场景中更方便地处理数据。扩展运算符(spread࿰…...

第22天:信息收集-Web应用各语言框架安全组件联动系统数据特征人工分析识别项目
#知识点 1、信息收集-Web应用-开发框架-识别安全 2、信息收集-Web应用-安全组件-特征分析 一、ICO图标: 1、某个应用系统的标示,如若依系统有自己特点的图标;一旦该系统出问题,使用该系统的网站都会受到影响; 2、某个公…...
后端-redis
Redis RedisString类型String类型的常用命令 Hash类型Hash类型的常用命令 List类型List类型的常用命令 Set类型Set类型的常用命令 SortedSet类型SortedSet类型的常用命令 Redis序列化缓存更新策略缓存穿透缓存雪崩缓存击穿 Redis Redis是一个key-value的数据库,key…...

开发场景中Java 集合的最佳选择
在 Java 开发中,集合类是处理数据的核心工具。合理选择集合,不仅可以提高代码效率,还能让代码更简洁。本篇文章将重点探讨 List、Set 和 Map 的适用场景及优缺点,帮助你在实际开发中找到最佳解决方案。 一、List:有序存…...

golangci-lint安装与Goland集成
golangci-lint安装与Goland集成 1.golangci-lint概述2.golangci-lint安装3.Goland 中集成 golangci-lint4.golangci-lint 的使用5.排除代码检查 1.golangci-lint概述 golangci-lint是用于go语言的代码静态检查工具集 官网地址:golangci-lint 特性: 快…...

金仓数据库安装-Kingbase v9-centos
在很多年前有个项目用的金仓数据库,上线稳定后就没在这个项目了,只有公司的开发环境还在维护,已经好多年没有安装过了,重温一下金仓数据库安装,体验一下最新版本,也做一个新版本的试验环境; 一、…...
条款6:auto推导若非己愿,使用显式类型初始化惯用法
一、代理类 所谓的代理类就是以模仿和增强一些类型的行为为目的存在的类 class MyArray { public:class MyArraySize{public:MyArraySize(int size) : theSize(size) {}int size() const { return theSize; }operator int() const { return theSize; }private:int theSize;};…...

蓝桥杯物联网开发板硬件组成
第一节 开发板简介 物联网设计与开发竞赛实训平台由蓝桥杯大赛技术支持单位北京四梯科技有限公司设计和生产,该产品可用于参加蓝桥杯物联网设计与开发赛道的竞赛实训或院校相关课程的 实践教学环节。 开发板基于STM32WLE5无线微控制器设计,芯片提供了25…...

视频汇聚融合云平台Liveweb一站式解决视频资源管理痛点
随着5G技术的广泛应用,各领域都在通信技术加持下通过海量终端设备收集了大量视频、图像等物联网数据,并通过人工智能、大数据、视频监控等技术方式来让我们的世界更安全、更高效。然而,随着数字化建设和生产经营管理活动的长期开展࿰…...

(aaai2025) FD2-Net: Frequency-Driven Feature Decomposition Network
论文:FD2-Net: Frequency-Driven Feature Decomposition Network for Infrared-Visible Object Detection 代码:https://github.com/like413/FD2-Net 这个论文核心思想认为:多源融合目标检测方法忽略了频率上的互补特征,如可见光图…...

深度学习之目标检测——RCNN
Selective Search 背景:事先不知道需要检测哪个类别,且候选目标存在层级关系与尺度关系 常规解决方法:穷举法,在原始图片上进行不同尺度不同大小的滑窗,获取每个可能的位置 弊端:计算量大,且尺度不能兼顾 Selective …...

2014年IMO第3题
在凸四边形 A B C D ABCD ABCD 中, ∠ A B C = ∠ A D C = π 2 \angle ABC=\angle ADC=\frac{\pi}{2} ∠ABC=∠ADC=2π, H H H 为 A A A 在 B D BD BD 上的投影, 在边 A B AB AB 上有一点 S S S, ∠ C H S − ∠ C S B = π 2 \angle CHS-\angle CSB=\frac{\pi}{2} …...

国高材服务 | 高分子结晶动力学表征——高低温热台偏光显微镜
众所周知,聚合物制品的实际使用性能(如光学透明性、硬度、模量等)与材料内部的结晶形态、晶粒大小及完善程度有着密切的联系,因此,对聚合物结晶形态等的研究具有重要的理论和实际意义。 随着结晶条件的不用,…...
跨站请求伪造之基本介绍
一.基本概念 1.定义 跨站请求伪造(Cross - Site Request Forgery,缩写为 CSRF)漏洞是一种网络安全漏洞。它是指攻击者通过诱导用户访问一个恶意网站,利用用户在被信任网站(如银行网站、社交网站等)的登录状…...

Hadoop集群(HDFS集群、YARN集群、MapReduce计算框架)
一、 简介 Hadoop主要在分布式环境下集群机器,获取海量数据的处理能力,实现分布式集群下的大数据存储和计算。 其中三大核心组件: HDFS存储分布式文件存储、YARN分布式资源管理、MapReduce分布式计算。 二、工作原理 2.1 HDFS集群 Web访问地址&…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...