为何timerfd结合epoll无法按预期工作?负载生成器计时异常
问题分析与解决
核心原因
timerfd的工作机制是:每次超时后,内核会向文件描述符写入一个64位无符号整数(记录超时次数),如果不读取这个值,内核会持续将该fd标记为可读状态,导致epoll_wait反复触发。你的代码在处理timer_fd事件时,完全没有读取这个计数器值,这就是epoll_wait在一个5秒周期内被触发上千次的直接原因。
修复代码
修改calculate_throughput函数中处理timer_fd的逻辑,添加读取计数器的操作:
if (events[i].data.fd == timer_fd) { // 必须读取timerfd的计数器值,否则内核会持续触发EPOLLIN事件 uint64_t expirations; ssize_t ret = read(timer_fd, &expirations, sizeof(expirations)); if (ret != sizeof(expirations)) { perror("read timerfd"); exit(1); } gettimeofday(&end, NULL); float wait_time_s = time_diff(&end, &start); float throughput = (float)total_requests / wait_time_s; printf("Throughput (requests/second): %f\n", throughput); gettimeofday(&start, NULL); total_requests = 0; // 重置请求计数,保证下一次计算的是新周期内的请求量 }
另外需要补充请求计数的线程安全更新逻辑:
- 添加全局变量与互斥锁:
// 全局区域添加 int total_requests = 0; pthread_mutex_t reqCountMutex = PTHREAD_MUTEX_INITIALIZER;
- 在
user_function中请求成功的位置(info->total_count++处)更新全局计数:
else{ info->total_count++; // 线程安全更新全局请求计数 pthread_mutex_lock(&reqCountMutex); total_requests++; pthread_mutex_unlock(&reqCountMutex); }
额外优化提示
- 全局变量
x的读写未加同步,多线程环境下存在竞态,调试完成后建议移除或添加互斥锁保护。 calculate_throughput函数中的total_requests初始值为0,但原代码没有任何地方递增它,必须通过上述线程安全的方式更新才能得到正确的吞吐量数据。
内容的提问来源于stack exchange,提问作者Sourav Paul
相关产品推荐
相关产品推荐

