使用 timerfd + epoll() 实现,简洁精确。
没定义 MU_ERROR 宏的话替换为 printf 即可。
mu_timer.h:
#ifndef _MU_TIMER_H_
#define _MU_TIMER_H_#ifdef __cplusplus
extern "C"
{
#endif#include <stdint.h>
#include <time.h>
#include <pthread.h>/*** @brief 定时器状态*/typedef enum{MU_TIMER_UNINITIALIZED,MU_TIMER_RUNNING,MU_TIMER_PAUSED} TimerStatus;/*** @brief 定时器回调类型*/typedef void (*MuTimerCallback)(void *arg);/*** @brief 定时器结构体*/typedef struct{int timerfd; ///< timerfd文件描述符struct itimerspec tmr; ///< 时间间隔TimerStatus status; ///< 当前状态int initialized; ///< 是否初始化int counter; ///< 剩余触发次数(-1为无限次)MuTimerCallback callback; ///< 回调函数void *arg; ///< 回调参数} MuTimer;/*** @brief 初始化定时器管理器** @return int 0成功,-1失败*/int mu_timer_init(void);/*** @brief 去初始化定时器管理器** @return int 0成功,-1失败*/int mu_timer_deinit(void);/*** @brief 创建并启动定时器** @param timer 定时器指针* @param interval 时间间隔* @param callback 回调* @param arg 回调参数* @param trigger_count 触发次数(-1为无限次)* @return int 0成功,-1失败* @note* 回调函数应尽量简洁,避免执行耗时操作,以免影响其他定时器的运行。* 当定时器达到设定的触发次数后,会自动销毁,无需手动调用 mu_timer_destroy*/int mu_timer_create(MuTimer *timer, struct timespec interval, MuTimerCallback callback,void *arg, int trigger_count);/*** @brief 暂停定时器** @param timer 定时器指针* @return int 0成功,-1失败*/int mu_timer_pause(MuTimer *timer);/*** @brief 恢复定时器** @param timer 定时器指针* @return int 0成功,-1失败*/int mu_timer_resume(MuTimer *timer);/*** @brief 重置定时器时间间隔** @param timer 定时器指针* @return 0成功,-1失败* @note 若定时器暂停,需恢复后才会计时*/int mu_timer_reset(MuTimer *timer);/*** @brief 设置定时器时间间隔** @param timer 定时器指针* @param interval 时间间隔* @return int 0成功,-1失败* @note 若定时器暂停,需恢复后才会计时*/int mu_timer_set_interval(MuTimer *timer, struct timespec interval);/*** @brief 销毁定时器** @param timer 定时器指针* @return int 0成功,-1失败*/int mu_timer_destroy(MuTimer *timer);#ifdef __cplusplus
}
#endif#endif // _MU_TIMER_H_
mu_timer.c:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include <sys/epoll.h>
#include <stdint.h>#include "mu_timer.h"
#include "mu_debug.h"#define MAX_EPOLL_EVENTS 32 ///< epoll一次最多处理的事件数// 定时器管理器结构体
typedef struct
{int epfd; // epoll文件描述符pthread_t event_thread; // 事件处理线程pthread_mutex_t mutex; // 管理器互斥锁int running; // 运行状态int initialized; // 初始化标记
} MuTimerManager;// 全局管理器实例
static MuTimerManager g_timer_manager = {0};// 规范化timespec
static void normalize_interval(struct timespec *interval)
{if (interval->tv_nsec >= 1000000000L){interval->tv_sec += interval->tv_nsec / 1000000000L;interval->tv_nsec %= 1000000000L;}
}// 处理定时器到期事件
static void handle_timer_expired(MuTimer *timer)
{pthread_mutex_lock(&g_timer_manager.mutex);if (!timer || !timer->initialized || timer->status != MU_TIMER_RUNNING){pthread_mutex_unlock(&g_timer_manager.mutex);return;}// 读取timerfd,清除可读状态uint64_t exp;ssize_t s = read(timer->timerfd, &exp, sizeof(uint64_t));if (s != sizeof(uint64_t)){MU_ERROR("read timerfd failed: %s", strerror(errno));{pthread_mutex_unlock(&g_timer_manager.mutex);return;}}// 更新计数器if (timer->counter > 0)timer->counter--;// 执行回调if (timer->callback){pthread_mutex_unlock(&g_timer_manager.mutex);timer->callback(timer->arg);pthread_mutex_lock(&g_timer_manager.mutex);}// 检查是否需要销毁定时器if (timer->counter == 0){pthread_mutex_unlock(&g_timer_manager.mutex);mu_timer_destroy(timer);pthread_mutex_lock(&g_timer_manager.mutex);}pthread_mutex_unlock(&g_timer_manager.mutex);
}// 事件处理线程
static void *timer_event_thread(void *arg)
{struct epoll_event events[MAX_EPOLL_EVENTS];while (g_timer_manager.running){int nfds = epoll_wait(g_timer_manager.epfd, events, MAX_EPOLL_EVENTS, 1000); // 1秒超时if (nfds == -1){if (errno == EINTR){continue;}MU_ERROR("epoll_wait failed: %s", strerror(errno));break;}for (int i = 0; i < nfds; i++){if (events[i].events & EPOLLIN){MuTimer *timer = (MuTimer *)events[i].data.ptr;handle_timer_expired(timer);}}}return NULL;
}// 初始化定时器管理器
int mu_timer_init(void)
{if (g_timer_manager.initialized){return -1;}// 创建epoll实例g_timer_manager.epfd = epoll_create1(EPOLL_CLOEXEC);if (g_timer_manager.epfd == -1){MU_ERROR("epoll_create1 failed: %s", strerror(errno));return -1;}// 创建事件处理线程if (pthread_create(&g_timer_manager.event_thread, NULL, timer_event_thread, NULL) != 0){MU_ERROR("pthread_create failed: %s", strerror(errno));close(g_timer_manager.epfd);g_timer_manager.epfd = 0;return -1;}pthread_mutex_init(&g_timer_manager.mutex, NULL);g_timer_manager.running = 1;g_timer_manager.initialized = 1;return 0;
}// 去初始化定时器管理器
int mu_timer_deinit(void)
{if (!g_timer_manager.initialized){return -1;}g_timer_manager.running = 0;// 等待事件处理线程结束pthread_join(g_timer_manager.event_thread, NULL);if (g_timer_manager.epfd > 0){close(g_timer_manager.epfd);}pthread_mutex_destroy(&g_timer_manager.mutex);memset(&g_timer_manager, 0, sizeof(g_timer_manager));return 0;
}int mu_timer_create(MuTimer *timer, struct timespec interval, MuTimerCallback callback,void *arg, int trigger_count)
{if (!timer || !callback || trigger_count == 0 ||interval.tv_sec < 0 || interval.tv_nsec < 0 ||(interval.tv_sec == 0 && interval.tv_nsec == 0) ||!g_timer_manager.initialized)return -1;memset(timer, 0, sizeof(MuTimer));// 创建timerfdtimer->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);if (timer->timerfd == -1){MU_ERROR("timerfd_create failed: %s", strerror(errno));return -1;}normalize_interval(&interval);// 设置timerfdtimer->tmr.it_interval = interval;timer->tmr.it_value = interval;if (timerfd_settime(timer->timerfd, 0, &timer->tmr, NULL) == -1){MU_ERROR("timerfd_settime failed: %s", strerror(errno));close(timer->timerfd);return -1;}timer->callback = callback;timer->arg = arg;timer->counter = trigger_count;timer->status = MU_TIMER_RUNNING;// 添加到epoll监听struct epoll_event ev;ev.events = EPOLLIN;ev.data.ptr = timer;if (epoll_ctl(g_timer_manager.epfd, EPOLL_CTL_ADD, timer->timerfd, &ev) == -1){MU_ERROR("epoll_ctl ADD failed: %s", strerror(errno));close(timer->timerfd);return -1;}timer->initialized = 1;return 0;
}int mu_timer_pause(MuTimer *timer)
{int ret = 0;if (!g_timer_manager.initialized)return -1;pthread_mutex_lock(&g_timer_manager.mutex);if (!timer || !timer->initialized){ret = -1;goto exit;}if (timer->status != MU_TIMER_RUNNING)goto exit;// 获取剩余时间if (timerfd_gettime(timer->timerfd, &timer->tmr) == -1){MU_ERROR("timerfd_gettime failed: %s", strerror(errno));ret = -1;goto exit;}// 停止timerfdstruct itimerspec its;memset(&its, 0, sizeof(its));if (timerfd_settime(timer->timerfd, 0, &its, NULL) == -1){MU_ERROR("timerfd_settime failed: %s", strerror(errno));ret = -1;goto exit;}timer->status = MU_TIMER_PAUSED;exit:pthread_mutex_unlock(&g_timer_manager.mutex);return ret;
}int mu_timer_resume(MuTimer *timer)
{int ret = 0;if (!g_timer_manager.initialized)return -1;pthread_mutex_lock(&g_timer_manager.mutex);if (!timer || !timer->initialized){ret = -1;goto exit;}if (timer->status != MU_TIMER_PAUSED || timer->counter == 0)goto exit;// 重新启动timerfdif (timerfd_settime(timer->timerfd, 0, &timer->tmr, NULL) == -1){MU_ERROR("timerfd_settime failed: %s", strerror(errno));ret = -1;goto exit;}timer->status = MU_TIMER_RUNNING;exit:pthread_mutex_unlock(&g_timer_manager.mutex);return ret;
}int mu_timer_reset(MuTimer *timer)
{int ret = 0;if (!g_timer_manager.initialized)return -1;pthread_mutex_lock(&g_timer_manager.mutex);if (!timer || !timer->initialized){ret = -1;goto exit;}// 重置超时时间timer->tmr.it_value = timer->tmr.it_interval;if (timer->status == MU_TIMER_RUNNING){if (timerfd_settime(timer->timerfd, 0, &timer->tmr, NULL) == -1){MU_ERROR("timerfd_settime failed: %s", strerror(errno));ret = -1;goto exit;}}exit:pthread_mutex_unlock(&g_timer_manager.mutex);return ret;
}int mu_timer_set_interval(MuTimer *timer, struct timespec interval)
{int ret = 0;if (!g_timer_manager.initialized || interval.tv_sec < 0 || interval.tv_nsec < 0 ||(interval.tv_sec == 0 && interval.tv_nsec == 0))return -1;pthread_mutex_lock(&g_timer_manager.mutex);if (!timer || !timer->initialized){ret = -1;goto exit;}normalize_interval(&interval);// 重新设置间隔timer->tmr.it_interval = interval;timer->tmr.it_value = interval;if (timer->status == MU_TIMER_RUNNING){if (timerfd_settime(timer->timerfd, 0, &timer->tmr, NULL) == -1){MU_ERROR("timerfd_settime failed: %s", strerror(errno));ret = -1;goto exit;}}exit:pthread_mutex_unlock(&g_timer_manager.mutex);return ret;
}int mu_timer_destroy(MuTimer *timer)
{int ret = 0;if (!g_timer_manager.initialized)return -1;pthread_mutex_lock(&g_timer_manager.mutex);if (!timer || !timer->initialized){ret = -1;goto exit;}// 从epoll中移除if (epoll_ctl(g_timer_manager.epfd, EPOLL_CTL_DEL, timer->timerfd, NULL) == -1){MU_ERROR("epoll_ctl DEL failed: %s", strerror(errno));ret = -1;}close(timer->timerfd);memset(timer, 0, sizeof(MuTimer));exit:pthread_mutex_unlock(&g_timer_manager.mutex);return ret;
}