深入理解:阻塞IO、非阻塞IO、水平触发与边缘触发
深入理解:阻塞IO、非阻塞IO、水平触发与边缘触发
在网络编程和并发处理中,理解不同的 I/O 模型和事件通知机制至关重要。本文将深入探讨阻塞IO(Blocking IO)、非阻塞IO(Non-Blocking IO)、水平触发(Level Triggering)以及边缘触发(Edge Triggering)这四个核心概念,帮助开发者更好地选择和使用合适的 I/O 模型。
一、阻塞IO(Blocking IO)
定义: 阻塞IO是最简单也是最常见的IO模型。当应用程序发起一个IO操作(例如,读取数据)时,如果数据尚未准备好,操作系统会将该线程或进程 阻塞 起来,直到数据准备就绪并被拷贝到用户空间后,该线程或进程才会继续执行。
工作方式:
- 用户进程发起一个读操作。
- 操作系统内核检查数据是否准备好。
- 如果数据没有准备好,内核会将该进程/线程挂起(阻塞)。
- 一旦数据准备好,内核将数据从内核空间拷贝到用户空间。
- 内核唤醒被挂起的进程/线程。
- 用户进程继续执行,完成IO操作。
优点: 编程模型简单直观,易于理解和实现。
缺点: 在等待IO完成期间,进程或线程会被阻塞,无法执行其他任务。这在高并发场景下会导致大量的线程被阻塞,效率低下。
示例: 默认情况下,socket 的 recv() 函数就是一个阻塞调用。如果接收缓冲区中没有数据,recv() 会一直等待直到有数据到达。
二、非阻塞IO(Non-Blocking IO)
定义: 非阻塞IO与阻塞IO相反。当应用程序发起一个IO操作时,如果数据尚未准备好,操作系统会立即返回一个错误(通常是 EAGAIN 或 EWOULDBLOCK),而不会阻塞该线程或进程。应用程序需要不断地轮询(polling)内核,检查数据是否已经准备好。
工作方式:
- 用户进程将 socket 设置为非阻塞模式。
- 用户进程发起一个读操作。
- 操作系统内核检查数据是否准备好。
- 如果数据没有准备好,内核会立即返回一个错误。
- 用户进程不会被阻塞,可以继续执行其他任务,并在稍后再次尝试读取数据。
- 一旦数据准备好,内核将数据拷贝到用户空间,并且下次用户进程尝试读取时会成功返回。
优点: 进程或线程在等待IO操作完成时不会被阻塞,可以执行其他任务,提高了并发处理能力。
缺点: 需要应用程序不断地轮询内核,检查IO操作是否完成,这会消耗大量的CPU资源,尤其是在大多数轮询都返回“数据未准备好”的情况下。
示例: 可以通过设置 socket 的 O_NONBLOCK 标志将其设置为非阻塞模式。此时,调用 recv() 如果没有数据会立即返回错误。
三、I/O 多路复用(The Need for)
非阻塞IO虽然避免了线程阻塞,但其轮询机制效率低下。为了更高效地处理多个连接的IO事件,出现了I/O多路复用技术,例如 select、poll 和 epoll。这些技术允许一个进程或线程同时监视多个文件描述符(例如,socket),一旦某个或某些文件描述符上的IO事件就绪(例如,有数据可读),内核就会通知应用程序。
在使用 I/O 多路复用时,我们需要关注事件的触发方式,这就是水平触发和边缘触发的概念。
四、水平触发(Level Triggering,LT)
定义: 水平触发是一种事件通知机制。当内核检测到文件描述符上的某个条件满足时(例如,socket 接收缓冲区中有数据可读),就会通知应用程序。 只要该条件持续满足,内核就会重复通知应用程序。
工作方式:
- 当使用
select或poll时,如果一个文件描述符就绪(例如,可读),select或poll会返回该文件描述符。即使应用程序没有完全读取完所有的数据,下次再次调用select或poll时,如果该文件描述符仍然处于就绪状态(缓冲区中还有数据),它仍然会被报告为就绪。 - 在使用
epoll时,如果以水平触发模式注册了一个文件描述符的读事件,只要该文件描述符的读缓冲区中还有数据,epoll_wait就会一直返回该文件描述符,直到所有数据都被读取完毕。
特点:
- 可靠性高:只要条件满足,就会一直通知,不容易丢失事件。
- 处理方式灵活:应用程序可以根据自己的节奏处理数据,不必一次性读取所有数据。
- 效率相对较低:可能会因为条件持续满足而产生不必要的重复通知。
适用场景: 对数据完整性要求较高,但对实时性要求不是特别苛刻的场景。select 和 poll 默认采用水平触发。epoll 默认也采用水平触发,但可以通过设置标志来使用边缘触发。
五、边缘触发(Edge Triggering,ET)
定义: 边缘触发是另一种事件通知机制。当内核检测到文件描述符上的状态 发生变化 时,才会通知应用程序。例如,当 socket 接收到新的数据时,会产生一个读事件的边缘触发。 只有在状态发生变化时才会通知一次。
工作方式:
- 在使用
epoll并以边缘触发模式注册了一个文件描述符的读事件时,只有当新的数据到达该文件描述符的读缓冲区时,epoll_wait才会返回该文件描述符。即使缓冲区中仍然有未读取的数据,如果后续没有新的数据到达,epoll_wait不会再次返回该文件描述符。
特点:
- 效率高:只有在状态发生变化时才通知,减少了不必要的重复通知。
- 要求高:应用程序需要及时地处理所有触发的事件,否则可能会丢失后续的事件。对于读事件,需要一次性读取所有可读的数据,对于写事件,需要在可写状态发生变化后尽可能多地写入数据。
适用场景: 对性能要求非常高的场景,需要应用程序能够快速且完整地处理事件。Nginx 等高性能服务器通常会选择使用 epoll 的边缘触发模式。
注意事项: 在使用边缘触发时,需要特别小心,确保在每次事件触发后都能够完全处理所有的数据,避免数据丢失或遗漏。通常会配合使用非阻塞IO,循环读取或写入数据直到返回错误(例如 EAGAIN)。
六、总结与比较
| 特性 | 阻塞IO | 非阻塞IO | 水平触发(LT) | 边缘触发(ET) |
|---|---|---|---|---|
| 行为 | 等待IO完成才返回 | 立即返回,可能出错或返回部分数据 | 只要条件满足(例如,有数据),就持续通知 | 只有在状态发生变化时才通知一次 |
| CPU 消耗 | 低(等待时不占用) | 高(需要轮询) | 适中 | 高(需要及时处理所有事件) |
| 编程复杂度 | 低 | 较高(需要处理错误和轮询) | 相对简单 | 较高(需要确保完整处理事件) |
| 可靠性 | 高 | 取决于轮询策略 | 高(不易丢失事件) | 较高,但需要正确处理,否则可能丢失事件 |
| 效率 | 低(并发处理能力差) | 较低(轮询开销) | 相对较低(可能重复通知) | 较高(减少了重复通知) |
| 常见应用 | 简单的客户端程序,单线程服务器 | 需要并发处理但对实时性要求不高的场景 | select,poll,epoll(默认) | epoll(通过设置 EPOLLET 标志) |
理解这四种概念对于进行高效的网络编程至关重要。在选择合适的IO模型和触发机制时,需要根据具体的应用场景、性能要求以及编程复杂度进行权衡。例如,对于需要处理大量并发连接且对性能要求极高的服务器,epoll 的边缘触发模式通常是一个不错的选择,但同时也需要开发者具备更高的编程技巧来确保程序的正确性。
相关文章:
深入理解:阻塞IO、非阻塞IO、水平触发与边缘触发
深入理解:阻塞IO、非阻塞IO、水平触发与边缘触发 在网络编程和并发处理中,理解不同的 I/O 模型和事件通知机制至关重要。本文将深入探讨阻塞IO(Blocking IO)、非阻塞IO(Non-Blocking IO)、水平触发&#x…...
WebRTC的ICE之TURN协议的交互流程中继转发Relay媒体数据的turnserver的测试
WebRTC的ICE之TURN协议的交互流程和中继转发Relay媒体数据的turnserver的测试 WebRTC的ICE之TURN协议的交互流程中继转发Relay媒体数据的turnserver的测试 WebRTC的ICE之TURN协议的交互流程和中继转发Relay媒体数据的turnserver的测试前言一、TURN协议1、连接Turn Server 流程①…...
HTTP---基础知识
天天开心!!! 文章目录 一、HTTP基本概念1. 什么是HTTP,又有什么用?2. 一次HTTP请求的过程3.HTTP的协议头4.POST和GET的区别5. HTTP状态码6.HTTP的优缺点 二、HTTP的版本演进1.各个版本的应用场景2、注意要点 三、HTTP与…...
Redis6数据结构之List类型
redis的List类型底层结构是双向链表,插入删除时间复杂度O(1)快,查找为O(n)慢。 应用场景:简单队列、最新评论列表、非实时排行榜(定时计算榜单,如笔记本日销榜单)。 常用命令: lpush将一个或多个值从左边…...
DeepSeek接入飞书多维表格,效率起飞!
今天教大家把DeepSeek接入飞书表格使用。 准备工作:安装并登录飞书;可以准备一些要处理的数据,确保数据格式正确,如 Excel、CSV 等,也可直接存储到飞书多维表格。 创建飞书多维表格:打开飞书,点…...
[FGPA基础学习]分秒计数器的制作
分秒计数器设计 本次实验内容为:DE2-115板子上用 Verilog编程实现一个 分秒计数器,并具备按键暂停、按键消抖功能 一、系统架构设计 顶层模块划分 顶层模块(top) ├── 按键消抖模块(key_debounce) ├…...
【Spring Boot 与 Spring Cloud 深度 Mape 之十】体系整合、部署运维与进阶展望
【Spring Boot 与 Spring Cloud 深度 Mape 之十】体系整合、部署运维与进阶展望 #微服务实战 #Docker #Kubernetes #SpringSecurity #OAuth2 #分布式事务 #Seata #ServiceMesh #总结 #SpringCloud #SpringBoot 系列终章:经过前九篇 [【深度 Mape 系列】] 的系统学习…...
【商城实战(97)】ELK日志管理系统的全面应用
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配,乃至运营推广策略,102 章内容层层递进。无论是想…...
高并发系统下的订单号生成服务设计与实现
目录 引言 订单号设计的关键考量因素 基础需求分析 唯一性保障 数据量预估 可读性设计 系统架构考量 分库分表兼容 可扩展性设计 技术选型与比较 性能优化 高可用性保障 实践案例:高并发系统订单号结构设计 结构详解 业务类型标识(2位) 唯一标识部分…...
每日算法-250329
记录今天学习的三道算法题:两道滑动窗口和一道栈的应用。 2904. 最短且字典序最小的美丽子字符串 题目描述 思路 滑动窗口 解题过程 题目要求找到包含 k 个 ‘1’ 的子字符串,并且需要满足两个条件: 最短长度:在所有包含 k 个 …...
向量数据库学习笔记(2) —— pgvector 用法 与 最佳实践
关于向量的基础概念,可以参考:向量数据库学习笔记(1) —— 基础概念-CSDN博客 一、 pgvector简介 pgvector 是一款开源的、基于pg的、向量相似性搜索 插件,将您的向量数据与其他数据统一存储在pg中。支持功能包括&…...
蓝桥杯 之 二分
文章目录 习题肖恩的n次根分巧克力2.卡牌 二分是十分重要的一个算法,常常用于求解一定范围内,找到满足条件的边界值的情况主要分为浮点数二分和整数二分二分问题,最主要是写出这个check函数,这个check函数最主要就是使用模拟的方法…...
从零开始研发GPS接收机连载——18、北斗B1的捕获和跟踪
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 从零开始研发GPS接收机连载——18、北斗B1的捕获和跟踪 B1信号的捕获B1信号的跟踪 前面已经验证了射频能够接收到B1的信号,通过FPGA采集了IQ信号之后能够通过matl…...
sqlalchemy:将mysql切换到OpenGauss
说明 之前python的项目使用的mysql,近期要切换到国产数据库OpenGauss。 之前的方案是fastapisqlalchemy,测试下来发现不用改代码,只要改下配置即可。 切换方案 安装openGauss-connector-python-psycopg2 其代码工程在:https:…...
memtest86检测内存
上次在R730安装万兆网卡的时候,使用过memtest64进行测试。这个操作肯定是有用的,我就用这个方法查出有问题的内存条,及时找商家进行了更换。 但是该方案有个问题,只能锁定部分内存,如下图,只测试到了23G左…...
OpenCV图像拼接(10)用于实现图像拼接过程中的时间流逝(timelapse)效果的一个类cv::detail::Timelapser
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::detail::Timelapser 是 OpenCV 库中用于实现图像拼接过程中的时间流逝(timelapse)效果的一个类。它通常用于将一系列…...
验证linux多进程时间片切换的程序
一、软件需求 在同时运行一个或多个一味消耗 CPU 时间执行处理的进程时,采集以下统计信息。 ・在某一时间点运行在逻辑 CPU 上的进程是哪一个 ・每个进程的运行进度 通过分析这些信息,来确认本章开头对调度器的描述是否正确。实验程序的…...
【Basys3】外设-灯和数码管
灯 约束文件 set_property PACKAGE_PIN W5 [get_ports CLK] set_property PACKAGE_PIN U18 [get_ports rst] set_property PACKAGE_PIN U16 [get_ports {led[0]}] set_property PACKAGE_PIN E19 [get_ports {led[1]}] set_property PACKAGE_PIN U19 [get_ports {led[2]}] set…...
axios文件下载使用后端传递的名称
java后端通过HttpServletResponse 返回文件流 在Content-Disposition中插入文件名 一定要设置Access-Control-Expose-Headers,代表跨域该Content-Disposition返回Header可读,如果没有,前端是取不到Content-Disposition的,可以在统…...
从零开始搭建Anaconda环境
Anaconda是一个流行的Python数据科学平台,包含conda包管理器、Python解释器和大量预装的数据科学工具包。以下是详细的安装和配置步骤: 1. 下载Anaconda 访问Anaconda官方网站 根据你的操作系统(Windows/macOS/Linux)选择相应版本 推荐下载Python 3.x版…...
TDengine 中的命名与边界
简介 本章主要介绍命名的合法字符集和限制规则,这对于正确使用 TDengine,减小报错很重要,这些规则在 SQL 语句中都生效,在使用过程中要注意,避免不必要的错误。 名称命名规则 合法字符:英文字符、数字和…...
软件架构设计中的软件过程模型初识
软件架构设计中的软件过程模型是指导软件开发过程的框架,它们定义了软件开发的不同阶段、活动、任务和角色。结合具体的使用场景,可以更好地理解这些模型如何在实际项目中应用。以下将详细介绍几种常见的软件过程模型,并结合典型场景进行讲解…...
基于ssm的课程辅助教学平台(全套)
互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对《离散结构》课程教学信息管理混乱,出错率高,信息安…...
[创业之路-344]:战略的本质是选择、聚焦, 是成本/效率/低毛利优先,还是差易化/效益/高毛利优先?无论是成本优先,还是差易化战略,产品聚焦是前提。
前言: 一、战略的本质是选择、聚焦 关于战略的本质,触及了商业竞争的核心矛盾:选择成本优先(效率/低毛利)还是差异化(效益/高毛利),本质上是对企业战略方向的终极拷问。 1、战略选…...
洛谷题单1-P5705 【深基2.例7】数字反转-python-流程图重构
题目描述 输入一个不小于 100 100 100 且小于 1000 1000 1000,同时包括小数点后一位的一个浮点数,例如 123.4 123.4 123.4 ,要求把这个数字翻转过来,变成 4.321 4.321 4.321 并输出。 输入格式 一行一个浮点数 输出格式 …...
Typora 小乌龟 git 上传到gitee仓库教程
首先进行资源分享 通过网盘分享的文件:TortoiseGit-LanguagePack-2.17.0.0-64bit-zh_CN.msi等4个文件 链接: https://pan.baidu.com/s/1NC8CKLifCEH_YixDU3HG_Q?pwdqacu 提取码: qacu --来自百度网盘超级会员v3的分享 首先将软件进行解压 看自己电脑的版本进行…...
【新人系列】Golang 入门(八):defer 详解 - 上
✍ 个人博客:https://blog.csdn.net/Newin2020?typeblog 📝 专栏地址:https://blog.csdn.net/newin2020/category_12898955.html 📣 专栏定位:为 0 基础刚入门 Golang 的小伙伴提供详细的讲解,也欢迎大佬们…...
知识图谱之知识抽取:从数据海洋中 “捞金”
目录 知识抽取:开启知识宝库的钥匙 知识抽取的对象:实体、关系与属性 知识抽取的方法:各显神通的 “淘金术” 基于规则的方法 机器学习方法 深度学习方法 知识抽取面临的挑战:荆棘丛中的探索 数据的多样性和复杂性 语义理…...
RAG - 五大文档切分策略深度解析
文章目录 切分策略1. 固定大小分割(Fixed-Size Chunking)2. 滑动窗口分割(Sliding Window Chunking)3. 自然语言单元分割(Sentence/Paragraph Segmentation)4. 语义感知分割(Semantic-Aware Seg…...
keil中文注释出现乱码怎么解决
keil中文注释出现乱码怎么解决 在keil–edit–configuration中encoding改为chinese-GB2312...
