参考文档
(1)http://www.cnblogs.com/dandingyy/articles/2653218.html
(2)http://baike.baidu.com/link?url=_npJrTewl6jAk2B0G-KDiluRkC09xDTezsnTy0bbqsdcqjTlMQMvQY-of9mLbcIeoxqqiW2DzwMT5xaqOqO9WK
(3)http://blog.csdn.net/liangyamin/article/details/7320608
在参考文献(1)中提到了“在linux下如果定时如果要求不太精确的话,使用alarm()和signal()就行了(精确到秒),但是如果想要实现精度较高的定时功能的话,就要使用setitimer函数。”因为我一开始就查的是setitimer函数,所以这里先介绍下这个函数吧。
一、 函数原型
int setitimer(intwhich, const struct itimerval *Value, struct itimerval *ovalue);
调用成功返回0,否则返回-1
which : 定时器类型,有3种选择
ITIMER_REAL:以系统真实事件来计算,它送出SIGALRM信号。
ITIMER_VIRTUAL:以该进程在用户态下话费的时间来计算,它送出SIGVTALRM信号。
ITIMER_PROF:以该进程在用户态下和内核态下所话费的时间来计算,它送出SIGPROF信号。
Value:其定义如下
struct itimerval {
struct timeval it_interval; // how long to run the first time
struct timeval it_value; // after the first time, how long to run next time
}
struct timeval {
long tv_sec; // 秒
long tv_usec; // 微秒
}
ovalue:用来保存先前的值,一般为NULL。如果不是NULL,将返回计时器原有值。
二、 程序例程
1. 示例1
#include
#include
#include
#include
#include
#include
void Func1()
{
static int iCnt1 = 0;
printf("The %d Times: Hello world in Func1()\n", iCnt1);
iCnt1++;
}
int main(void)
{
struct itimerval tv,otv;
signal(SIGALRM,Func1);
//how long to run the first time
tv.it_value.tv_sec = 1;
tv.it_value.tv_usec = 0;
//after the first time, how long to run next time
tv.it_interval.tv_sec = 3;
tv.it_interval.tv_usec = 0;
if(setitimer(ITIMER_REAL, &tv, &otv) != 0)
printf("setitimer err %d\n", errno);
while(1)
{
pause();
}
}
2. 示例2
#include
#include
#include
#include
#include
#include
void Func1()
{
static int iCnt1 = 0;
printf("The %d Times: Hello world in Func1()\n", iCnt1);
iCnt1++;
}
void Func2()
{
static int iCnt2 = 0;
printf("The %d Times:Hello world in Func2()\n", iCnt2);
iCnt2++;
}
int main(void)
{
struct itimerval tv,otv;
signal(SIGALRM,Func1);
//how long to run the first time
tv.it_value.tv_sec = 1;
tv.it_value.tv_usec = 0;
//after the first time, how long to run next time
tv.it_interval.tv_sec = 3;
tv.it_interval.tv_usec = 0;
if(setitimer(ITIMER_REAL, &tv, &otv) != 0)
printf("setitimer err %d\n", errno);
//假如说有两个定时,都用setitimer(ITIMER_REAL, &tv, &otv)这种方法定义
struct itimerval tv1,otv1;
signal(SIGALRM,Func2);
tv1.it_value.tv_sec = 10;
tv1.it_value.tv_usec = 0;
tv1.it_interval.tv_sec = 20;
tv1.it_interval.tv_usec = 0;
if(setitimer(ITIMER_REAL, &tv1, &otv1) != 0)
printf("setitimer2 err %d\n", errno);
while(1)
{
//sleep(1);
//printf("otv: %d, %d, %d, %d\n", otv.it_value.tv_sec, otv.it_value.tv_usec, otv.it_interval.tv_sec, otv.it_interval.tv_sec);
pause();
}
}
这里要特别做如下的说明:
一个进程只能使用一个setitimer函数,这个并不想QT里面的信号与槽的这种机制,其实其只发出一个SIGALRM,与定义了多少个itimerval类型的变量无关。所以如果有两个setitimer函数,第二个函数会把第一次调用时设置的参数给覆盖了。第一次定义的是每个3s执行一次,第二次定义的是每个20s执行一次,实际上程序执行后,打印的节奏确实是20s执行一次。signal函数虽然设置了两次,同样第二次把第一次给覆盖了,当计时时间到了,并不会执行Func1函数,而是会执行Func2函数。
后面再研究参考文献(1)中提到的alarm()和signal()方法,另外一点就是,setitimer函数底层如何进行微秒级的一个定时的,内核中驱动如何处理的。
欢迎交流共同学习 QQ群:485158261