定时器分类
硬件定时器:由硬件频率和触发限制的大小决定,只有一个,精度高
软件定时器:基于硬件定时器实现,精度大于等于硬件定时器,但通过软件(代码)实现,所以实现的个数没有上限
定时器相关分类
单次:就是定时器设置一个时间,当到达该时间后就会退出,该定时器将被销毁,不再起作用
周期:就是定时器只要设置一次,后面将定期触发定时器
超时函数:定时器超时后执行的函数
中断上下文:就是中断处理中执行超时函数,每次时间变化都会触发中断,自然而然都有机会执行超时函数,那么实时性很高
任务上下文:就是超时函数作为一个进程来执行,超时后也需要调度才能执行,实时性差
软件定时器设计
初始化
time结构体中有函数指针和调用该函数的参数和定时的时间
初始化中会将每个time结构体赋值为空
创建
找到一个还没有被设置的time结构体然后赋值
删除
找到对应的time结构体然后赋值为空
触发流程
时间中断,然后时间中断处理函数中触发关于检查是否要触发软中断函数的函数,如果符合某个软件定时器的定时数字就会调用该软件定时器的处理函数
图形示意
每次硬件定时器中断触发tick变化,然后timecheck会将timelist中不同timer的定时的数字对比,然后决定是否触发其处理函数
优化
- 由于每次timecheck都需要循环挨个比对,如果让时间快到的放在前面,那么能比对的次数会少些,所以按照超时时间排序
- 链表实现的是对空间的优化,如果用数组来存储软件定时器,那么可能导致某些没被用的空间浪费掉,采用链表需要就申请空间,能够节约空间
进一步优化比对的次数,跳表算法,类似二分,从上层往下层比对。
如果为20,首先到达11发现小于26,此时到下层,发现大于17,到达17,发现小于26,调到下一层,再次比对20,比对成功
代码
在创建软件定时器函数时,会在开始和最后又上锁和解锁,试想下,目标是实现创建软件定时器实现在当前时刻几秒后软件定时器能按时触发。如果中间有定时中断发送,那么定时器设置到一半,就会去处理中断,此时也会去检查软件定时器,假设此时软件定时器想的是当前时刻的一个时刻后,那么此时由于中断中会将该时刻加一个,但检查时候由于软件定时器没有设置完成,那么会导致错过这个时刻,要等到下次定时器中断才会检查软件定时器并成功调用其中处理函数