linux 定时器管理系统设计与实现
linux 定时器管理系统设计与实现
1. 模块概述
SL Timebase 模块是一个轻量级的定时器管理系统,专为嵌入式应用设计。该模块通过单一线程实现多个定时任务的并发执行,避免了为每个定时任务单独创建线程的资源开销。模块采用秒级精度的计时机制,适用于对时间精度要求不高但需要稳定性的场景。
2. 设计目标与原则
- 资源高效性:通过单线程管理多个定时任务,减少系统资源消耗
- 简单易用:提供简洁明了的API接口
- 可扩展性:支持动态添加定时任务
- 可靠性:提供稳定的定时执行机制
- 低耦合:定时器与具体业务逻辑解耦,通过回调函数实现业务处理
3. 核心数据结构
3.1 定时器配置结构体
typedef struct {
unsigned int interval_sec; // 时间间隔(秒)
void (*callback)(void); // 回调函数
unsigned int counter; // 计数器
} sl_timebase_config_t;
各字段详细说明:
interval_sec
:定时器触发的时间间隔,单位为秒callback
:定时器触发时执行的回调函数,无参数无返回值counter
:内部计数器,用于追踪经过的时间,当达到interval_sec
时触发回调
3.2 全局配置
#define MAX_TIMEBASE_COUNT 16 // 最大支持的定时器数量
static sl_timebase_config_t g_timebase_configs[MAX_TIMEBASE_COUNT] = {{0}};
static int g_timebase_count = 0;
全局变量说明:
g_timebase_configs
:定时器配置数组,最多支持16个定时器g_timebase_count
:当前已配置的定时器数量
4. 模块API详解
4.1 添加定时器
int sl_timebase_add_timer(unsigned int interval_sec, void (*callback)(void))
功能:向系统中添加一个新的定时器任务
参数:
interval_sec
:定时器触发间隔,单位为秒callback
:定时器触发时执行的回调函数
返回值:
SL_EOK
:添加成功SL_ERROR
:添加失败(例如定时器数量已达上限)
实现细节:
- 检查当前定时器数量是否已达到最大限制
- 将新定时器的配置信息存入全局数组
- 初始化计数器为0
- 递增定时器计数
4.2 定时器线程初始化
int sl_timebase_thread_init(void)
功能:初始化并启动定时器管理线程
返回值:
SL_EOK
:初始化成功
实现细节:
- 创建一个新的线程,入口函数为
sl_timebase_thread_entry
- 线程创建为分离态(detached),资源会在线程结束时自动回收
4.3 定时器线程主函数
void *sl_timebase_thread_entry(void *arg)
功能:定时器管理线程的主函数,负责所有定时器的计时和触发
实现细节:
- 将线程设置为分离态
- 初始化默认定时任务(网络监控和参数更新检查)
- 进入无限循环:
- 遍历所有定时器配置
- 递增每个定时器的计数器
- 当计数器达到设定的间隔时,执行对应的回调函数并重置计数器
- 休眠1秒
5. 内置定时任务详解
5.1 网络状态监控(net_eth0_check_callback)
static void net_eth0_check_callback(void)
功能:监控eth0网络接口的状态,在网络从断开到连接的状态转换时触发系统重启
执行周期:2秒
实现细节:
- 设置初始启动延迟(60秒),等待DHCP完成
- 通过读取
/sys/class/net/eth0/carrier
文件获取网络接口状态 - 将状态转换为数字表示(1表示连接,0表示断开)
- 检测状态转换,当检测到从断开到连接的转换时触发系统重启
- 更新上一次的网络状态记录
关键点:
- 使用静态变量
last_state
记录上一次的网络状态,初始值为-1表示未初始化 - 使用静态变量
init_delay
实现启动延迟,避免系统启动初期不稳定状态的误判
5.2 参数更新检查(dc_param_update_check_callback)
static void dc_param_update_check_callback(void)
功能:检查系统参数更新标志,触发相应的事件处理
执行周期:60秒
实现细节:
- 检查参数更新标志的状态
- 如果标志为启用状态,则:
- 记录日志
- 重置更新标志
- 创建并触发事件19
6. 工作流程与时序
- 系统初始化阶段调用
sl_timebase_thread_init()
- 创建定时器管理线程,线程自动添加默认的定时任务
- 线程进入循环,每秒遍历所有定时器,更新计数器
- 当某定时器计数器达到其设定的间隔值时,执行对应的回调函数
- 其他模块可以通过
sl_timebase_add_timer()
添加自定义定时任务
7. 性能与资源考量
- 线程资源:整个模块仅使用一个线程,资源消耗小
- 时间精度:精度为秒级,不适用于需要毫秒级响应的场景
- 扩展性限制:最多支持16个定时器,若需更多需修改
MAX_TIMEBASE_COUNT
- CPU占用:每秒仅做简单的计数器递增和条件判断,CPU占用极低
8. 使用示例
8.1 基本使用
// 初始化定时器系统
if (sl_timebase_thread_init() != SL_EOK) {
// 处理错误
}
// 定义回调函数
void temperature_monitor(void) {
// 检查温度传感器
// 处理异常温度
}
// 添加一个每10秒执行一次的温度监控任务
if (sl_timebase_add_timer(10, temperature_monitor) != SL_EOK) {
// 处理错误
}
8.2 注意事项
-
回调函数应当遵循以下原则:
- 执行时间应尽量短,避免长时间阻塞定时线程
- 不应包含阻塞操作
- 如需执行耗时操作,应在回调中创建新线程或使用任务队列
-
定时任务添加应当考虑:
- 避免过多的短周期任务,可能会增加系统负担
- 相近周期的任务可考虑合并,在同一回调中处理多项功能
9. 扩展与优化建议
- 优先级机制:为不同的定时任务添加优先级机制
- 动态管理:实现定时器的动态移除功能
- 精度提升:增加毫秒级的定时支持
- 错误处理:增强回调函数的异常处理机制
- 状态监控:添加定时器状态的统计和监控功能
10. 调试与日志
当前模块使用SL_LOG
宏进行日志记录,主要记录以下事件:
- 网络状态文件访问失败
- 网络状态读取失败
- 网络状态从断开到连接的转换
- 参数更新检查触发
11. 安全性考虑
- 线程安全:目前的实现不保证线程安全,若多线程同时调用
sl_timebase_add_timer()
可能导致竞争条件 - 回调函数安全:未对回调函数的执行进行异常保护,一个回调的崩溃可能导致整个定时器系统崩溃
12. 总结
SL Timebase模块是一个简单高效的定时器管理系统,通过单线程多任务的方式优化了系统资源的使用。它提供了秒级精度的定时执行能力,适用于多种嵌入式应用场景。模块的设计遵循了低耦合、易用性和资源效率的原则,为系统提供了稳定可靠的定时服务支持。