您的位置:首页 > 运维架构 > Linux

Linux定时器分析-源码sample

2015-06-03 22:05 309 查看
/*

 * time_test.c

 *

 *  Created on: 2015年6月3日

 *      Author: gcooq

 */

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <signal.h>

#include <time.h>

#include <sys/time.h>

#include <sys/queue.h>

#define MAX_TIMER_NUM 1000

#define TIMER_START 1

#define TIMER_TICK 1   //一个tick滴答

#define INVALID_TIMER_ID  (-1)  //无效ID

#ifndef TRUE

#define TRUE 1

#endif

#ifndef FALSE

#define FALSE 0

#endif

typedef int  timer_id;  //计时器的ID

//当一个timer时间满时调用timer_expiry()函数

typedef int timer_expiry(timer_id id,void *user_data,int len);

/*timer结构定义*/

struct timer{
LIST_ENTRY(timer)  entries;//list  entry
timer_id id;
//timer的ID
int  interval;                                         //timer间隔
int elapse;                                          //timer
timer_expiry *cb;               //如果时间满则调用
void *user_data;             //回调参数
int len;                               //user_data 长度

};

//timer list

struct timer_list{
LIST_HEAD(listheader,timer)  header;    //list header
int num;                                                    //计时器实体数目
int max_num;                                           //最大的实体数目
void  (*old_sigfunc)(int);                //保存之前的信号句柄Handler
void (*new_sigfunc)(int);            //信号句柄
struct itimerval ovalue;                  //旧的时间值
struct itimerval value;                 //our internal timer value

};

//函数操作

int  init_timer(int count);

int destroy_timer(void);

timer_id add_timer(int interval,timer_expiry *cb,void *user_data,int len);

int del_timer(timer_id id);

static struct timer_list timer_list;

static void sig_func(int signo);

//创建一个计时器

//返回值返回0表示成功

int init_timer(int count){

    int ret=0;

    if(count<=0||count>MAX_TIMER_NUM){

    printf("计时器最大数量为%d.\n",MAX_TIMER_NUM);

    return -1;//失败

    }

    memset(&timer_list,0,sizeof(struct timer_list));//分配内存

    LIST_INIT(&timer_list.header);

    timer_list.max_num=count;  //构造队列

    //注册内部信号句柄并且存储旧的信号句柄

    if((timer_list.old_sigfunc=signal(SIGALRM,sig_func))==SIG_ERR){

    return -1;

    }

    timer_list.new_sigfunc=sig_func;

    //设置内部计时器驱动多计时器和村粗就得计时器值

    timer_list.value.it_value.tv_sec=TIMER_START;

    timer_list.value.it_value.tv_usec=0;

    timer_list.value.it_interval.tv_sec=TIMER_TICK;

    timer_list.value.it_interval.tv_usec=0;

    ret=setitimer(ITIMER_REAL,&timer_list.value,&timer_list.ovalue);

    return ret;

}

//删除timerlist

int destroy_timer(void){
struct timer *node=NULL;
if((signal(SIGALRM,timer_list.old_sigfunc))==SIG_ERR){
return -1;
}
if((setitimer(ITIMER_REAL,&timer_list.ovalue,&timer_list.value))<0){
return -1;

}
while(!LIST_EMPTY(&timer_list.header)){ ///直到队列为空
node=LIST_FIRST(&timer_list.header);
LIST_REMOVE(node,entries);
//释放node
printf("移除 id %d\n",node->id);
free(node->user_data);
free(node);
}
memset(&timer_list,0,sizeof(struct timer_list));
return 0;

}

//增加计时器到计时器列表中

/*

 * cb cb!=NULL&&timer expiry,调用

 * 返回值为计时器ID  if==INVALID_TIMER ,添加失败

 * */

timer_id add_timer(int interval,timer_expiry *cb,void *user_data,int len){

struct timer *node=NULL;
if(cb==NULL||interval<=0){
return INVALID_TIMER_ID;
}
if(timer_list.num<timer_list.max_num){
timer_list.num++;
}
else{
return INVALID_TIMER_ID;//list加满了

}
if((node=malloc(sizeof(struct timer)))==NULL){
return INVALID_TIMER_ID;
}
if(user_data!=NULL||len!=0){
node->user_data=malloc(len);
memcpy(node->user_data,user_data,len);
node->len=len;
}
node->cb=cb;
node->interval=interval;
node->elapse=0;
node->id=timer_list.num;
LIST_INSERT_HEAD(&timer_list.header,node,entries);
return node->id;

}

//Delete  a timer from time list

int del_timer(timer_id id){

if(id<0||id>timer_list.max_num){
return -1;
}
struct timer *node=timer_list.header.lh_first;
for(;node!=NULL;node=node->entries.le_next){
printf("Total timer num 是 %d /timer id %d.\n",timer_list.num,id);
if(id==node->id){
LIST_REMOVE(node,entries);
timer_list.num--;
free(node->user_data);
free(node);
return 0;
}
}

//找不到计时器
return -1;

}

/*Tick Bookkeeping*/

static void sig_func(int signo){
struct timer *node=timer_list.header.lh_first;
for(;node!=NULL;node=node->entries.le_next){
node->elapse++;
if(node->elapse>=node->interval){ //说明tick大于允许的间隔时间大于或者等于的话将执行cb回调函数
node->elapse=0;
node->cb(node->id,node->user_data,node->len);
}
}

}

static char *fmt_time(char *tstr){
//格式化时间
time_t t;
t=time(NULL);
strcpy(tstr,ctime(&t));
tstr[strlen(tstr)-1]='\0';//结束字符
return tstr;

}

//单元测试

timer_id  id[3];

timer_id call_cnt=0;

int timer1_cb(timer_id id,void *arg,int len){
char tstr[200];
static int i,ret;

printf("欢迎 [%s] /id %d:timer1_cb is here.\n",fmt_time(tstr),id);
if(i>10){
ret=del_timer(id);
printf("timer1_cb:%s del_timer/id %d::ret=%d\n",fmt_time(tstr),id,ret);
}
i++;
call_cnt++;
return 0;

}

int timer2_cb(timer_id id,void *arg,int len){
char tstr[200];
static int i,ret;

printf("欢迎 [%s] /id %d:timer2_cb is here.\n",fmt_time(tstr),id);
if(i>10){
ret=del_timer(id);
printf("timer2_cb:%s del_timer/id %d::ret=%d\n",fmt_time(tstr),id,ret);
}
i++;
call_cnt++;
return 0;

}

int timer3_cb(timer_id id,void *arg,int len){
char tstr[200];
static int i,ret;
printf("欢迎 [%s] /id %d:timer3_cb is here.\n",fmt_time(tstr),id);
if(i>10){
ret=del_timer(id);
printf("timer1_cb:%s del_timer/id %d::ret=%d\n",fmt_time(tstr),id,ret);
}
i++;
call_cnt++;
return 0;

}

int main(void ){  //主函数
char arg[50];
char args[100];
char tstr[200];
int ret;
struct timespec time;
time.tv_sec=0;  //秒
time.tv_nsec=100000000;  //微毫秒

init_timer(MAX_TIMER_NUM);//初始化

id[0]=add_timer(1,timer1_cb,NULL,0);
printf("注册timer id[0]=%d\n",id[0]);

id[1]=add_timer(2,timer2_cb,arg,50);
printf("注册timer id[1]=%d\n",id[1]);

id[2]=add_timer(3,timer3_cb,args,100);
printf("注册timer id[2]=%d\n",id[2]);
while(1){
if(call_cnt>10){
break;
}
nanosleep(&time,NULL);
}
ret=destroy_timer();
printf("mainL%s destroy_timer,ret=%d\n",fmt_time(tstr),ret);
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 源码 多线程