Linux定时器分析-源码sample
2015-06-03 22:05
399 查看
/*
* 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;
}
* 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 socket 初步
- 从源码安装Mysql/Percona 5.5
- Python3写爬虫(四)多线程实现数据爬取
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断
- 谁是桌面王者?Win PK Linux三大镇山之宝
- vivi下重新调整分区
- Linux VS Unix:Linux欲一统天下 Unix不死