IO多路复用的两种触发机制:ET和LT触发机制。以及IO操作是异步的还是同步的理解

本片文章主要讨论两个问题:

  1. ET触发机制为什么必须搭配非阻塞IO实现?
  2. 如果判断IO操作是异步的还是同步的?

我们都知道 IO 多路复用有三种时间的通知模式:

其一是 select 模式;其二是 poll 模式;其三是 epoll 模式。而在 epoll 模式中,又有两种触发机制。一种是 LT(LevelTriggered)水平触发,另一种是 ET(EdgeTriggered)边缘触发。

我简单提及一下 epoll 模式的两种事件的触发机制:

① 一种是每次调用 epoll_wait 的时候,进行 FD 的写回操作,这种通知机制叫 LevelTriggered 水平触发,每当调用 epoll_wait 的时候都会进行一次触发,如果缓冲区的内容还没有读完,下次触发的时候,FD 会再次重写回用户区的 events 数组中。

② 另一种是调用 epoll_wait 之后,进行 FD 的写回操作,并且会清空内核区 ready_list 的 FD 内容,这种通知机制叫 EdgeTriggered 边缘触发。在这种情况下如果 recvfrom 没有读完内核缓冲区的内容,那么就会出现数据漏读,事件丢失的现象,所以边缘触发一定要结合非阻塞 IO 实现(下面将详细讲解这个)。


为了进一步理解 LT 触发机制,需要明确 LT 模式的触发情况:

  • 只要内核 buffer 里有数据,epoll_wait 就会通知这个 FD 可读

然后进一步理解阻塞和非阻塞,就需要从系统调用行为去看:

  • 用户进程调用 raed 后,如果没有数据可读,内核会让用户进程挂起,一直等到条件满足(有数据)才返回
  • 用户进程调用 read 后,如果没有数据,立刻返回 -1,并设置 errno=EAGAIN/EWOULDBLOCK,不会等待数据到来

在下面的场景中,用户 buffer 只有 1kb 空间,内核 buffer 中有 2kb。如果采用的是 LT + 非阻塞,那么用户读取了 1kb 之后,因为 LT 的机制(buffer 没读取完就会再次触发epoll_wait)会再次调用epoll_wait让用户去读取数据(再次调用的根本原因是 LT 触发机制)

在下面的场景中,用户 buffer 有 2kb 空间,内核 buffer 中有 1kb。如果采用的是 LT + 阻塞 ,那么用户读取了 1kb 之后,继续等待数据,用户进程因为没读取到要求的数据量会进入阻塞等待状态(这个等待就是正常等待新数据,没有达到 read 的返回条件,连接未断开且读缓存未满 )。下次有新数据来的时候,会因为 LT 触发机制,会再次调用 epoll_wait 读取数据

在下面的场景中,用户 buffer 有 2kb 的空间,内核 buffer 中有 1kb 的空间。如果采用的是 ET + 非阻塞,并且此时调用的 read 函数中,想要读取的大小是 2kb。用户首先将内核 buffer 中 1kb 的数据读取完毕,其次会就直接结束返回,不会进行死等状态,即使没有读到想要的数据大小。当然这个 FD 所对应的 Socket 在后续的时间写入了最后的 1kb,ep_poll_callback会再次触发,然后在下一次调用epoll_wait时,用户想要的数据都会被读取到

用户 buffer 有 2kb 的空间,内核 buffer 中有 1kb 的空间。如果采用的是 ET + 阻塞 ,并且此时调用的 read 函数中,想要读取的大小是 2kb。用户首先将内核 buffer 中 1kb 的数据读取完毕,其次会进入死等状态。因为用户没有读取到想要的数据量,所以选择阻塞等待。但问题就在于,ET 模式只会在有新的数据时才进行触发,如果没有新数据到达,那 read 就将一直死等,并且如果用户 buffer 再一次读取中没有把内核 buffer 中的数据全部读光,那么可能永远不会有新通知提醒用户线程"buffer 还有数据"

最后关于 IO 操作是同步还是异步这个问题,我们关键看数据在内核空间与用户空间的拷贝过程(数据读写的 IO 操作)是同步还是异步,如果从内核的buffer中将数据拷贝到用户空间的buffer的操作是内核线程完成的,那么这个IO操作就是异步的;反之如果操纵是用户线程完成的,那么IO操作就是同步的

相关推荐
程序员泠零澪回家种桔子4 分钟前
OpenManus开源自主规划智能体解析
人工智能·后端·算法
Remember_99315 分钟前
Spring 核心原理深度解析:Bean 作用域、生命周期与 Spring Boot 自动配置
java·前端·spring boot·后端·spring·面试
kiss strong31 分钟前
springboot替换word模板&加入二维码&加水印&转为pdf
spring boot·后端·pdf
Stecurry_3033 分钟前
Springboot整合SpringMVC --从0到1
java·spring boot·后端
JaguarJack43 分钟前
PHP 现在可以零成本构建原生 iOS 和 Android 应用 NativePHP for Mobile v3 发布
后端·php·laravel·服务端
一点程序12 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
怪兽源码14 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
csdn_aspnet14 小时前
ASP.NET Core 中的依赖注入
后端·asp.net·di·.net core
昊坤说不出的梦15 小时前
【实战】监控上下文切换及其优化方案
java·后端
疯狂踩坑人15 小时前
【Python版 2026 从零学Langchain 1.x】(二)结构化输出和工具调用
后端·python·langchain