IO复用+定时

学习IO复用和定时操作时,利用AI生成的示例

IO复用 + 定时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <chrono>
#include <cerrno>
#include <cstdio>
#include <sys/epoll.h>

// 定义超时时间常量(5秒)
const std::chrono::steady_clock::duration TIMEOUT = std::chrono::milliseconds(5000);
// 预计算超时毫秒数,避免重复转换
const int TIMEOUT_MS = std::chrono::duration_cast<std::chrono::milliseconds>(TIMEOUT).count();

int main() {
// 假设已初始化epfd、events和MAX_EVENTS_NUM
int epfd = -1;
struct epoll_event events[1024]; // 示例大小
const int MAX_EVENTS_NUM = 1024;

int timeout = TIMEOUT_MS; // 初始超时时间
std::chrono::steady_clock::time_point start;
std::chrono::steady_clock::time_point end;

while (true) {
start = std::chrono::steady_clock::now();
int event_count = epoll_wait(epfd, events, MAX_EVENTS_NUM, timeout);

// 处理epoll_wait错误
if (event_count < 0) {
if (errno != EINTR) { // 非信号中断的错误才退出
std::perror("epoll_wait failed");
break;
}
// 信号中断则继续等待,不修改超时时间
continue;
}
// 处理超时情况
else if (event_count == 0) {
// 超时后重置超时时间
timeout = TIMEOUT_MS;
// 可以添加超时处理逻辑
continue;
}

// 计算实际等待时间(毫秒)
end = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();

// 更新剩余超时时间
timeout -= static_cast<int>(elapsed);
// 确保超时时间不会为负
if (timeout < 0) {
timeout = 0;
}

// 处理事件(示例)
// handle_events(events, event_count);
}

return 0;
}

核心逻辑:用 epoll_wait 的“超时”实现定时

epoll_wait 是 Linux 下 I/O 复用的核心系统调用,它有一个超时参数(代码里的 timeout):

  • 如果在 timeout 时间内,没有 I/O 事件就绪,epoll_wait 会返回 0,表示“超时”。

  • 如果有 I/O 事件就绪,epoll_wait 会返回就绪的事件数量(大于 0),并提前返回。

代码正是利用“epoll_wait 超时返回 0”这个特性,来实现定时触发

以下是这种 “IO 复用 + 定时” 模式的典型应用场景:

  1. 高性能网络服务器

  • 场景描述:如 Web 服务器、游戏服务器等,需要同时处理大量客户端连接(I/O 事件),同时还需执行定时任务(如定时清理空闲连接、定时推送心跳包、定时统计服务器状态等)。

  • 示例:一个 Web 服务器,既需要处理客户端的 HTTP 请求(I/O 事件),又需要每 5 秒检查一次所有连接,关闭长时间无活动的连接(定时任务)。使用该模式可以在同一个线程中高效完成这两类操作,避免多线程开销。

  1. 网络监控与管理系统

  • 场景描述:需要监控多个网络设备的状态(通过 I/O 读取设备数据),同时定时生成监控报告、定时发送告警信息。

  • 示例:一个服务器集群监控系统,需要实时监听各服务器的状态变化(I/O 事件),同时每 1 分钟生成一次性能统计报表(定时任务)