水平触发(Level-Triggered)与边沿触发(Edge-Triggered)的区别
核心区别
特性 | 水平触发(LT) | 边沿触发(ET) |
---|---|---|
触发条件 | 只要缓冲区有数据/可写就会持续通知 | 仅在状态变化时通知一次(如空→非空) |
事件处理要求 | 不需要一次性处理完所有数据 | 必须一次性处理完所有数据,否则会丢失事件 |
性能开销 | 可能因重复通知产生额外系统调用 | 系统调用次数更少,性能更高 |
典型实现 | select /poll /默认的epoll LT 模式 |
epoll ET 模式 |
技术细节对比
读事件场景
- LT模式:只要接收缓冲区有数据,每次调用
epoll_wait()
都会返回该socket的可读事件。 - ET模式:仅在以下情况触发:
- 新数据到达时(从无到有)
- 接收缓冲区从满变为非满后又有新数据到达
- LT模式:只要接收缓冲区有数据,每次调用
写事件场景
// ET模式下必须非阻塞写入,直到EAGAIN
while (send(sock, buf, len, MSG_DONTWAIT) > 0);
代码实现差异 “`cpp // LT模式简单处理(可能多次触发) if (events[i].events & EPOLLIN) { read(fd, buf, sizeof(buf)); }
// ET模式必须循环读取到EAGAIN if (events[i].events & EPOLLIN) {
while ((n = read(fd, buf, sizeof(buf))) > 0);
if (errno != EAGAIN) error();
}
---
#### **选择建议**
1. **优先使用ET的场景**
- 需要高性能的服务器(如nginx、redis)
- 能保证一次性完整处理事件的场景
2. **适合LT的场景**
- 简单应用或调试阶段
- 无法保证及时处理所有数据的场景
---
#### **底层原理图示
数据到达 持续通知(LT) 仅通知一次(ET)
▲-------► │ │
│ ▼ ▼
Socket缓冲区 [#####] → epoll_wait()返回 → epoll_wait()返回一次
│ │ │
├-----未读完-----► ▼ X (不再通知)
│ 再次epoll_wait()返回
”`
📌 关键记忆点:
- LT像”持续提醒的闹钟”,ET像”单次触发的机关”
- Redis采用ET+非阻塞IO,Java NIO默认使用LT
内容由零声教学AI助手提供,问题来源于学员提问