1.定时器结构体定义
typedef struct sttimers sttimers;
typedef void (*timeout_callback_t)(sttimers* timer,void* userdata);
struct sttimers{
unsigned int timeout; //超时时间
sttimers* next;
void * userdata; //用户数据
timeout_callback_t timeout_callback; //超时回调函数
};
2.定时器操作的相关API
- 定时器的并不是动态实现,故在使用该软件定时器之前,需要定义一个静态链表句柄,以及运行时间的检测变量(注意要是无符号整型变量哦);
static sttimers* timerlist = NULL;
volatile unsigned int uwTick = 0;
static void sttimer_timetick_run(){
uwTick++;
}
static unsigned int sttimers_getuwtick(){
return uwTick;
}
- 定时器时间粒度的注册;
/**************************************************************
* 函数名称:sttimers_timeticks_register
* 函数功能:定时器时间粒度设置为1ms(可调)
* 函数参数: 无
* 函数返回:
* 成功:0
* 失败:<0
**************************************************************/
int sttimers_timeticks_register(void){
if(signal(SIGALRM,sttimer_timetick_run)==SIG_ERR){
return -1;
}
struct itimerval newtime;
newtime.it_value.tv_sec = 0;
newtime.it_value.tv_usec = 1000;
newtime.it_interval.tv_sec = 0;
newtime.it_interval.tv_usec = 1000;
if(setitimer(ITIMER_REAL,&newtime,NULL)<0){
return -2;
}
return 0;
}
- 定时器开始与停止;
/**************************************************************
* 函数名称:sttimers_start
* 函数功能:开启定时器,并更新定时器链表
* 函数参数:
* timer :定时器
* timming :定时时间
* callback:超时回调函数
* userdata:用户数据
* 函数返回:
* 0:成功
* -1:失败
**************************************************************/
int sttimers_start(sttimers* timer,unsigned int timing,timeout_callback_t callback,void* userdata){
if(!timer||!callback) return -1;
sttimers** nextTimer = & timerlist;
//移除定时器链表中旧的定时器
for(;*nextTimer!=NULL;nextTimer=&((*nextTimer)->next)){
if(timer==*nextTimer){
*nextTimer=timer->next;
break;
}
}
//初始化该定时器
timer->timeout_callback=callback;
timer->timeout = sttimers_getuwtick() + timing;
timer->userdata=userdata;
//插入定时器
for(nextTimer = &timerlist;;nextTimer=&((*nextTimer)->next)){
//如果定时器链表为空,插入链表头
if(*nextTimer==NULL){
timer->next = NULL;
*nextTimer = timer;
break;
}
//链表不为空,按超时时间的长短插入
if(timer->timeout < (*nextTimer)->timeout){
timer->next = *nextTimer;
*nextTimer = timer;
break;
}
}
return 0;
}
/**************************************************************
* 函数名称:sttimers_stop
* 函数功能:停止定时器,从定时器链表中移除
* 函数参数:
* timer :定时器
* 函数返回: 无
**************************************************************/
void sttimers_stop(sttimers* timer){
sttimers** nextTimer = &timerlist;
for(;*nextTimer;nextTimer = &((*nextTimer)->next)){
if(timer==*nextTimer){
*nextTimer = timer->next;
break;
}
}
}
- 定时器调度;
/**************************************************************
* 函数名称:sttimers_yield
* 函数功能:定时器调度,执行超时回调函数,更新定时器链表
* 函数参数:无
* 函数返回:首个定时器剩余的时间
**************************************************************/
int sttimers_yield(void){
sttimers* firstTimer = timerlist;
for(;firstTimer;firstTimer = firstTimer->next){
if(sttimers_getuwtick() < firstTimer->timeout){
//如果首个定时器未到时间,则返回其剩余的时间
return (int)(firstTimer->timeout - sttimers_getuwtick());
}
//到时间后,从定时器链表中移除首个定时器
timerlist = timerlist->next;
//并调用该定时器的超时回调函数
if(firstTimer->timeout_callback){
firstTimer->timeout_callback(firstTimer,firstTimer->userdata);
}
return 0;
}
}
3.测试用例
- 测试程序中设置三个定时器,分别进行1s,2s周期定时与3s单次定时,代码如下:
#if 1 //测试用例
#define USER_TIMER_CNT 3
struct TimerPara{
unsigned int val;
unsigned int interval;
timeout_callback_t callback;
void* userdata;
};
//设置的定时器个数
sttimers userTimer[USER_TIMER_CNT];
//每个定时器的超时回调函数声明
static void userTimer1_callback(sttimers* timer,void* userdata);
static void userTimer2_callback(sttimers* timer,void* userdata);
static void userTimer3_callback(sttimers* timer,void* userdata);
//每个定时器的参数
struct TimerPara userPara[USER_TIMER_CNT]={
{1000, 1000, userTimer1_callback, "user timer1--1000ms"},
{2000, 2000, userTimer2_callback, "user timer2--2000ms"},
{3000, 0, userTimer3_callback, "user timer3--3000ms"}
};
//超时回调函数实现
static void userTimer1_callback(sttimers* timer,void* userdata){
printf("%s\r\n",(char*)userdata);
sttimers_start(timer,userPara[0].interval,userPara[0].callback,userdata);
}
static void userTimer2_callback(sttimers* timer,void* userdata){
printf("%s\r\n",(char*)userdata);
sttimers_start(timer,userPara[1].interval,userPara[1].callback,userdata);
}
static void userTimer3_callback(sttimers* timer,void* userdata){
printf("%s\r\n",(char*)userdata);
}
int main(int argc,char** argv){
//注册定时器链表时间粒度
sttimers_timeticks_register();
//开启定时器
for(int i = 0;i < USER_TIMER_CNT;i++){
sttimers_start(&userTimer[i],
userPara[i].val,
userPara[i].callback,
userPara[i].userdata);
}
//定时器调度
while(1){
sttimers_yield();
}
return 0;
}
#endif
- 在linux环境下运行结果如下,三个定时器基本满足定时要求,设计符合基本思想和要求,感兴趣的朋友可以自行下载测试呦~
![](https://img-blog.csdnimg.cn/7152bdfdbab04f199b5b7bee7b090084.png)