概述 linux c本身不支持对timer的封装,使用定时器不像java那样的方便,一般有三种方法使用:1、while+sleep;2、alarm;3、timer_create。下面分别对三种方法进行举例。
一、举例
1、while+sleep
优点是可以完全控制暂停恢复,确定是需要控制线程的生命周期。
#include? <pthread.h>
#include? <sys/time.h>
#include? <stdio.h>
#include? <stdlib.h>
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? <unistd.h>
#include? <stdio.h>
#include? <stdlib.h>
#include? <signal.h>
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? <stdio.h>
#include? <stdlib.h>
#include? <signal.h>
#include? <time.h>
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? <stdio.h>
#include? <stdlib.h>
#include? <signal.h>
#include? <time.h>
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_handler\n");
?????? 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);
?}
|