16定时器

简单定时器

#include<unistd.h>

unsigned int alarm(unsigned int seconds)

      返回上一个alarm等待时间,没有则返回0

      只能设置 1 个定时器,设置第 2 个时会替换第一个

      设置成功后,上一个alarm会失效

      定时事件只执行1次,多次执行需要递归调用

等待事件到达后,会给进程发送 SIGALRM信号

      捕获 SIGALRM信号并处理

例子:

int g_nValue=0;

void fun(int sig)

{

      printf("sig:%d\n",sig);

      printf("g_nValue=%d\n",g_nValue);

}

void testAlarm()

{

      printf("pid:%d\n",getpid());

      //printf("1\n");

      int n=0;

      n=alarm(1);

      //printf("%d\n",n);

      //printf("2\n");

      signal(SIGALRM,fun);

      //printf("3\n");

      while(1)

      {

           g_nValue++;

      }

}

注意:alarm()定时器结束后,才发出SIGALRM信号。如alarm(100),不是启动alarm就发出,而是启动后100秒才发出信号。

一个定时器多次使用:

只需在信号处理函数再一次使用alarm()即可。

void fun(int sig)

{

      printf("sig:%d\n",sig);

      printf("g_nValue=%d\n",g_nValue);

      alarm(1);

}

alarm只能一个定时器,如果要该定时器不同秒数启动。即实现多个定时器的功能。

方式:设置一个标志位,用来标志秒数

void fun(int sig)

{

      static flag=0;

      flag++

      //1秒

      alarm(flag);

      if(flag%2==0)

      {

           //2秒

           alarm(flag);

      }

      if(flag%5==0)

      {   

           //5秒

           alarm(flag);

      }

      //...............

      printf("sig:%d\n",sig);

}

sleep与定时器的区别:

sleep是使程序进入休眠状态,即sleep后面的代码不会继续运行,直到休眠结束。

alarm定时器开始后,代码也会继续往下运行。

sleep对定时器的影响:

void fun(int sig)

{

      //printf("sig:%d\n",sig);

      printf("!");

      alarm(1);

}

void testAlarm()

{

      printf("pid:%d\n",getpid());

      int n=0;

      n=alarm(1);

      signal(SIGALRM,fun);

      while(1)

      {

           sleep(10);

           printf("@");

      }

}

结果输出:

pid:9282

!@!@!@.......

问题:定时器是1秒,sleep是10秒。不应该是10个!才是一个@吗?

此时就涉及到进程调度问题。程序原是运行态,sleep使程序进入了睡眠态。但是睡眠态无法直接回到运行态,只能到就绪态,等待cpu执行。

精准定时器

<sys/select.h>

<sys/time.h>

int getitimer(int which, struct itimerval *value)

int setitimer(int which, struct itimerval *new, struct itimeval *old)

which取值:提供三种定时器,可以同时存在

ITIMER_REAL           (0)

发送信号:SIGALRM

定义真实CPU时间(所有进程的CPU时间都累计),同 alarm

ITIMER_VIRTUAL     (1)

发送信号:SIGVTALRM

定义进程在用户态下的实际执行时间(只累计自己用户态的CPU时间)

ITIMER_PROF          (2)

发送信号:   SIGPROF

定义进程在用户态和内核态的实际执行时间(只累计自己的CPU时间)

注意:因为alarm 和ITIMER_REAL都是发出同一个信号SIGALRM,因此larm 和 setitimer(ITIMER_REAL, ...) 不能同时使用

struct itimerval

{

      struct timeval it_interval;  //下次定时取值;后续定时间隔时间

      struct timeval it_value;     //本次定时设置值;定时器第一次到达时间

}

struct timeval {

        time_t      tv_sec;         /* 秒 */

        suseconds_t tv_usec;        /* 微妙 */

};

定时器开始后

1.  先把 it_value 减少到0

2.  把 it_interval 复制给 it_value; (it_inverval=0则停止定时器)

3.  继续下一次定时循环

例子:

void func(int sig)

{

      //printf("sig:%d\n",sig);

      switch(sig)

      {

      case SIGALRM:

           {   

                 printf("SIGALRM....\n");

                 break;

           }

      case SIGVTALRM:

           {   

                 printf("SIGVTALRM....\n");

                 break;

           }

      case SIGPROF:

           {   

                 printf("SIGPROF....\n");

                 break;

           }

      }

}

void testMircoTimer()

{

      printf("pid:%d\n",getpid());

      struct itimerval new;

      //本次定时器间隔秒数

      new.it_interval.tv_sec=0;

      new.it_interval.tv_usec=500*1000;    //0.5

     

      //下次定时器间隔秒数

      new.it_value.tv_sec=1;

      new.it_value.tv_usec=500*1000; //0.5

     

      //创建三种定时器

      setitimer(ITIMER_REAL,&new,NULL);

      setitimer(ITIMER_VIRTUAL,&new,NULL);

      setitimer(ITIMER_PROF,&new,NULL);

     

      signal(SIGALRM,func);

      signal(SIGVTALRM,func);

      signal(SIGPROF,func);

     

      while(1)

      {

          

      }

}

猜你喜欢

转载自www.cnblogs.com/gd-luojialin/p/9216005.html