概述
linux c本身不支持对timer的封装,使用定时器不像java那样的方便,一般有三种方法使用:1、while+sleep;2、alarm;3、timer_create。下面分别对三种方法进行举例。
一、举例
1、while+sleep
优点是可以完全控制暂停恢复,确定是需要控制线程的生命周期。
#include
#include
#include
#include
typedef void (*TIMER_CALLBACK)(void);
static int s_wait_time=0;
static TIMER_CALLBACK s_call_back;
static int s_timer_flag=0;
static pthread_t s_pt;
static void sleep_ms(unsigned int msecs)
{
struct timeval tval;
tval.tv_sec = msecs / 1000;
tval.tv_usec = (msecs * 1000) % 1000000;
select(0, NULL, NULL, NULL, &tval);
}
//定时器线程
static void* thread_runner(void* param)
{
int time = 0;
printf("thread_run:pthread_self()=[%d]n",pthread_self());
while(s_timer_flag)
{
sleep_ms(s_wait_time);
if(s_call_back!=NULL)
{
s_call_back();
}
}
printf("thread_stop:pthread_self()=[%d]n",pthread_self());
return NULL;
}
//打开定时器
int starttimer(int time_million_second,TIMER_CALLBACK callback)
{
s_wait_time=time_million_second;
s_timer_flag=1;
s_call_back=callback;
pthread_create(&s_pt,NULL,thread_runner,NULL);
}
//关闭定时器
int stoptimer()
{
s_timer_flag = 0;
//暂停定时器也可以结束线程
//pthread_cancel(s_pt);
}
static void timer_routie()
{
static int times = 0;
printf("timer_routie:times=[%d]n",times++);
}
int main()
{
starttimer(1000,timer_routie);
sleep(5);
stoptimer();
sleep(1);
}
2、alarm
优点是实现简单,确定是信号会导致sleep和pause提前结束
#include#include #include #include typedef void (*TIMER_CALLBACK)(void); static int s_wait_time=0; static TIMER_CALLBACK s_call_back; static int s_timer_flag=0; void signal_handler(int siganl) { printf("signal_handler:siganl=[%d]n",siganl); if(siganl==SIGALRM) { if(s_call_back!=NULL) { s_call_back(); alarm(s_wait_time/1000); } } } //打开定时器 int starttimer(int time_million_second,TIMER_CALLBACK callback) { s_call_back=callback; s_wait_time=time_million_second; signal(SIGALRM,signal_handler); alarm(s_wait_time/1000); } //关闭定时器 int stoptimer() { s_wait_time=NULL; } static void timer_routie() { static int times = 0; printf("timer_routie:times=[%d]n",times++); } int main() { int count=5; starttimer(1000,timer_routie); //alarm会导致sleep和pause停止阻塞直接返回,所以这里需要循环 while(count--) { pause(); } stoptimer(); }
3、timer_create signal模式,此方式也会导致pause、sleep等函数提前返回
#include
#include
#include
#include
typedef void (*TIMER_CALLBACK)(void);
static int s_wait_time=0;
static TIMER_CALLBACK s_call_back;
static pthread_t s_pt;
static timer_t s_timerid;;
void signal_handler(int siganl)
{
printf("signal_handler:siganl=[%d]n",siganl);
if(siganl==SIGRTMAX)
{
if(s_call_back!=NULL)
{
s_call_back();
}
}
}
//打开定时器
int starttimer(int time_million_second,TIMER_CALLBACK callback)
{
s_wait_time=time_million_second;
s_call_back=callback;
signal(SIGRTMAX,signal_handler);
clockid_t clockid=CLOCK_REALTIME;
struct sigevent sev;
sev.sigev_notify=SIGEV_SIGNAL;
sev.sigev_signo=SIGRTMAX;
sev.sigev_value.sival_ptr=&s_timerid;
//创建定时器
timer_create(clockid,&sev,&s_timerid);
int flags=0;
struct itimerspec new_value;
new_value.it_value.tv_sec=1;
new_value.it_value.tv_nsec=0;
new_value.it_interval.tv_sec=1;
new_value.it_interval.tv_nsec=1;
//struct itimerspec old_value;
//启动定时器
timer_settime(s_timerid,flags,&new_value,NULL);
}
//关闭定时器
int stoptimer()
{
timer_delete(s_timerid);
printf("stoptimer:s_timerid=[%d]n",s_timerid);
}
static void timer_routie()
{
static int times = 0;
printf("timer_routie:times=[%d]n",times++);
}
int main()
{
int count=5;
starttimer(1000,timer_routie);
while(count--)
{
pause();//timer_create也会触发信号量导致sleep/usleep和pause立刻返回
}
stoptimer();
sleep(10);
}
4、timer_create thread模式,此模式不会导致sleep和pause提前返回,但是会额外创建线程,使用过多的定时器会额外使用内存。
#include#include #include #include typedef void (*TIMER_CALLBACK)(void); static int s_wait_time=0; static TIMER_CALLBACK s_call_back; static pthread_t s_pt; static timer_t s_timerid;; void timer_handler(union sigval sig) { printf("signal_handlern"); if(s_call_back!=NULL) { s_call_back(); } } //打开定时器 int starttimer(int time_million_second,TIMER_CALLBACK callback) { s_wait_time=time_million_second; s_call_back=callback; clockid_t clockid=CLOCK_REALTIME; struct sigevent sev; sev.sigev_notify=SIGEV_THREAD; sev.sigev_signo=SIGRTMAX; sev.sigev_value.sival_ptr=&s_timerid; sev.sigev_notify_function=timer_handler;//设置定时器回调 //创建定时器 timer_create(clockid,&sev,&s_timerid); int flags=0; struct itimerspec new_value; new_value.it_value.tv_sec=1; new_value.it_value.tv_nsec=0; new_value.it_interval.tv_sec=1; new_value.it_interval.tv_nsec=1; //struct itimerspec old_value; //启动定时器 timer_settime(s_timerid,flags,&new_value,NULL); } //关闭定时器 int stoptimer() { timer_delete(s_timerid); printf("stoptimer:s_timerid=[%d]n",s_timerid); } static void timer_routie() { static int times = 0; printf("timer_routie:times=[%d]n",times++); } int main() { int count=5; starttimer(1000,timer_routie); while(count--) { pause();//timer_create的thread类型不会触发信号量,也就不会导致sleep/usleep和pause立刻返回 } stoptimer(); sleep(10); }



