定时器函数SetTime与setitimer

时间:2022-09-18 23:31:23


一、Windows下的定时器函数

当程序种需要每隔一段时间执行一件事的时候,就需要使用SetTimer函数了。使用定时器的方法比较简单,通常定义一个时间间隔,然后WINDOWS以此时间间隔周期性的触发程序。通常有两种方法来实现:

1〉 发送WM_TIMER消息。

2〉 调用应用程序定义的回调函数

1、 SetTimer函数

1>   API函数SetTimer的原型

UINT_PTRSetTimer(
  HWND hWnd,              // 窗口句柄
  UINT_PTR nIDEvent,      // 定时器ID,多个定时器时,可以通过该ID判断是哪//个定时器
  UINT uElapse,           // 时间间隔,单位为毫秒
  TIMERPROC lpTimerFunc   // 回调函数
);


例如 :

SetTimer(m_hWnd,1,1000,NULL);   //窗口m_hWnd中一个ID为1的1秒触发一次的定时器

2>  MFC程序中的SetTimer

在MFC程序中SetTimer被封装在CWnd类中。调用就不用指定窗口句柄了。于是SetTimer函数的原型变为:

UINT SetTimer(
UINT nIDEvent,     // 定时器ID,多个定时器时,可以通过该ID判断是哪/个定时器
UINT nElapse,       // 时间间隔,单位为毫秒
void(CALLBACKEXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD) // 回调函数
);

例:

SetTimer(1,1000,NULL);//一个ID为1的1秒触发一次的定时器

2、 回调函数

1〉 发送WM_TIMER消息,SetTimer(1,1000,NULL);

SetTimer的第三个参数是一个回调函数,在这个函数里,放入你想要做的事情的代码,将它设定为NULL,也就是使用系统默认的回调函数onTime函数。在需要计时器的类的生成onTime函数的方法:

在ClassWizard里,选择需要计时 器的类,添加WM_TIME消息映射,就自动生成onTime函数了。

然后在函数里添加代码,让代码实现功能。每隔一段时间就会自动执行一次。

2〉 调用应用程序定义的回调函数

首先定义一个回调函数:

void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINTnTimerid,DWORD dwTime);

然后再用SetTimer(1,100,TimerProc)函数来建一个定时器,第三个参数就是回调函数地址。

3、 多个定时器

当程序中需要在不同的时刻执行不同的事件的时候,就需要定义多个定时器。通过定时ID来区分。

SetTimer(2,1000,NULL);
SetTimer(3,500,NULL);

 

此时onTimer函数体也要发生变化,要在函数体内添加每一个timer的处理代码:

 

onTimer(nIDEvent)
 
{
 
switch(nIDEvent)
 
{
 
case 1:........;
 
break;
 
case 2:.......;
 
break;
 
case 3:......;
 
break;
 
}
 
}

二、Linux下的定时器函数

1. Alarm

1〉 alarm函数

函数原型:

unsigned int alarm(unsigned int seconds);

头文件:

#include<unistd.h>


作用:

alarm函数,用来定时,当到达定时的时间后,内核会发送SIGALRM信号给进程,默认会结束进程。当然,也可以通过signal函数为信号SIGALRM设置处理函数。

如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。

返回值:如果调用此alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。 出错返回-1。

2〉例子

例一:使用默认信号处理函数,接收到SIGALRM后结束进程

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int main(int argc,char *argv[])
{
       alarm(3);
       int i =0;
       for(i=0;i<3;i++)
       {
              printf("%d\n",i);
              sleep(1);
       }
       printf("end");
       return0;
}

输出结果:

0

1

2

alarm signal

例二:通过signal函数指定处理函数

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
unsigned a;
void fun(int sig);
int main(int argc,char *argv[])
{
       alarm(3);
       signal(SIGALRM,fun);
       inti=0;
       for(i=0;i<3;i++)
       {
              printf("%d\n",i);
              sleep(1);
       }
       printf("end\n");
       return0;
}
void fun(int sig)
{
       if(sig== SIGALRM)
       printf("gettimer alarm!\n");
       else
       printf("gettimer failed!\n");
}

运行结果:
定时器函数SetTime与setitimer

例三:查看不同情况下alarm 的返回值

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
unsigned a;
void fun(int sig);
int main(int argc,char *argv[])
{
       unsignedint a,b;
       alarm(10);
       sleep(5);
       a=alarm(0);
       printf("Therest time of the first alarm is %u\n",a);
       b=alarm(3);
       signal(SIGALRM,fun);
       inti=0;
       for(i=0;i<3;i++)
       {
              printf("%d\n",i);
              sleep(1);
       }
       printf("Thereturn valuable of the last alarm is %u\nend\n",b);
       return0;
}
void fun(int sig)
{
       if(sig== SIGALRM)
       printf("gettimer alarm!\n");
       else
       printf("gettimer failed!\n");
}

输出结果:
定时器函数SetTime与setitimer

2.  setitimer

setitimer()为Linux的API,与C语言的StandardLibrary中的SetTimer不同。setitimer()有两个功能,

一是指定一段时间后,才执行某个function,类似alarm,但是精度高。

二是每间格一段时间就执行某个function,与windows下SetTimer 功能类似

以下程序demo如何使用setitimer()

1>  setitimer函数

函数原型:

int setitimer(
int which,
const structitimerval *restrict value,
struct itimerval*restrict ovalue
);

头文件:

#include <sys/time.h>

参数分析:

a. which: 指定定时器类型

setitimer支持3种类型的定时器:

ITIMER_REAL: 以系统真实的时间来计算,它送出SIGALRM信号。

ITIMER_VIRTUAL: -以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。

ITIMER_PROF: 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。

b. value:  结构itimerval的一个实例,用来设定定时时间。

结构体itimerval和timeval定义如下:

structitimerval 
{  
     struct timerval it_interval;  //指定间隔时间
     struct timerval it_value;  //指定初始定时时间
}


 itimerval.it_value设定第一次执行function所延迟的秒数, itimerval.it_interval设定以后每几秒执行function。

所以若只想延迟一段时间执行function,只要设定 itimerval.it_value即可。

若要设定间格一段时间就执行function,则it_value和it_interval都要设定,否则 funtion的第一次无法执行,就别说以后的间隔执行了。

两者都清零,会清除定

tv_sec提供秒级精度,tv_usec提供微秒级精度,以值大的为先,注意1s = 1000000us。

struct timeval 
{ 
     long tv_sec;  
     long tv_usec; 
}

   

c. ovalue: 用来保存先前的值,可不做处理,通常为NULL。  

返回值:setitimer()调用成功返回0,否则返回-1。

 

2>  例子

例一:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
 
void printMsg(int sig);
int main(int argc,char *argv[])
{
       int res= 0;
       signal(SIGALRM,printMsg);
      
       structitimerval tick;
       memset(&tick,0,sizeof(tick));
      
       tick.it_value.tv_sec= 3;
       tick.it_value.tv_usec= 0;
      
       tick.it_interval.tv_sec= 1;
       tick.it_interval.tv_usec= 0;
      
       res =setitimer(ITIMER_REAL,&tick,NULL);
      
       if(res)
       {
              printf("Settimer failed!!\n");
       }
       int i =0;
       for(i=0;i<10;i++)
       {
              printf("%d\n",i);
              sleep(1);
       }
       printf("Theend!\n");
       return0;
}
void printMsg(int sig)
{
       if(sig== SIGALRM)
       printf("gettimer alarm!\n");
       else
       printf("gettimer failed!\n");
}


输出结果 :
定时器函数SetTime与setitimer

例二:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
 
void printMsg(int sig);
int main(int argc,char *argv[])
{
       int res= 0;
       signal(SIGALRM,printMsg);
      
       structitimerval tick;
       memset(&tick,0,sizeof(tick));
      
       tick.it_value.tv_sec= 3;
       tick.it_value.tv_usec= 4000000;
      
       tick.it_interval.tv_sec= 1;
       tick.it_interval.tv_usec= 0;
      
       res =setitimer(ITIMER_REAL,&tick,NULL);
      
       if(res)
       {
              printf("Settimer failed!!\n");
       }
       int i =0;
       for(i=0;i<10;i++)
       {
              printf("%d\n",i);
              sleep(1);
       }
       printf("Theend!\n");
       return0;
}
void printMsg(int sig)
{
       if(sig== SIGALRM)
       printf("gettimer alarm!\n");
       else
       printf("gettimer failed!\n");
}

输出结果:
定时器函数SetTime与setitimer

例三:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
 
void printMsg(int sig);
int main(int argc,char *argv[])
{
       int res= 0;
       signal(SIGALRM,printMsg);
      
       structitimerval tick,old_tick;
       memset(&tick,0,sizeof(tick));
       memset(&tick,0,sizeof(old_tick));
       tick.it_value.tv_sec= 3;
       tick.it_value.tv_usec= 0;
      
       tick.it_interval.tv_sec= 1;
       tick.it_interval.tv_usec= 0;
      
       res =setitimer(ITIMER_REAL,&tick,&old_tick);
      
       if(res)
       {
              printf("Settimer failed!!\n");
       }
       int i =0;
       for(i=0;i<10;i++)
       {
              printf("%d\n",i);
              printf("value.sec= %ld ,value.usec = %ld \ninterval.sec = %ld ,interval.usec = %ld\n",old_tick.it_value.tv_sec,old_tick.it_value.tv_usec,old_tick.it_interval.tv_sec,old_tick.it_interval.tv_usec);
              sleep(1);
       }
       printf("Theend!\n");
       return0;
}
void printMsg(int sig)
{
       if(sig== SIGALRM)
       printf("gettimer alarm!\n");
       else
       printf("gettimer failed!\n");
}

输出结果:

定时器函数SetTime与setitimer