概述
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);

 }

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐