epoll两种触发方式

本文对比分析了LT(水平触发)和ET(边缘触发)两种I/O事件通知机制。LT模式下,只要文件描述符就绪,内核就会持续通知,直至变为未就绪状态;而ET模式仅在描述符首次变为就绪时通知一次,之后须通过IO操作使其变为未就绪状态才能重新触发。两种模式分别适用于不同的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,直至变为未就绪状态,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表。
  ET (edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),故上层须对fd进行IO操作,直至fd变为未就绪状态,否则epoll被不再被触发。在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认。
在C的epoll中,有两种主要类型的触发事件:边缘触发(Edge-triggered)和水平触发(Level- 这种模式下,当指定的条件首次满足(如数据可用或可读)时,epoll_wait会立即返回。例如,如果你只关心某个文件描述符变为可读,一旦数据到达,epoll就会报告这个事件。 - 示例代码(假设我们有一个socket并监听读事件): ```c // 添加到epoll struct epoll_event ev; ev.events = EPOLLIN; // 只关注读事件 ev.data.fd = sockfd; // sockfd是我们想要监控的socket epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &ev); // 监听事件 while (1) { int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (num_events > 0) { for (i = 0; i < num_events; i++) { if (events[i].data.fd == sockfd && events[i].events & EPOLLIN) { handle_data(sockfd); // 数据已准备就绪,处理数据 } } } } ``` 2. **水平触发(Level-triggered)**: - 在这种模式下,epoll_wait会一直等到有新的事件发生(无论之前是否已经发生了该事件),然后才会返回。如果一个文件描述符在多次轮询中都保持某种状态,比如一直可读,epoll_wait会在每次迭代中报告这个事件。 - 示例代码类似,只是在处理事件时有所不同: ```c while (1) { int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (num_events > 0) { for (i = 0; i < num_events; i++) { if (events[i].data.fd == sockfd) { // 只关心sockfd if (events[i].events & EPOLLIN) { handle_data(sockfd); // 如果是新发生的可读事件,处理数据 } } } } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值