Linux定时函数介绍:
在程序开发过程中,我们时不时要用到一些定时器,通常如果时间精度要求不高,可以使用sleep,uslepp函数让进程睡眠一段时间来实现定时,
前者单位为秒(s),后者为微妙(us);但有时候我们又不想让进程睡眠阻塞在哪儿,我们需要进程正常执行,当到达规定的时间时再去执行相应的操作,
在linux下面我们一般使用alarm函数跟setitimer函数来实现定时功能;
下面对这两个函数进行详细分析:
(1)alarm函数
alarm也称为闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号;
alarm函数原型如下:
1 unsigned int alarm(unsigned int seconds); 2 3 //seconds 为指定的秒数
1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 #include <signal.h> 5 6 void func() 7 { 8 printf("this is func "); 9 } 10 11 int main() 12 { 13 14 signal(SIGALRM, func); //2s后要执行的函数 15 alarm(2);//设置定时2s 16 17 while (1); 18 19 return 0; 20 }
(2)setitimer()函数
在linux下如果对定时要求不太精确的话,使用alarm()和signal()就行了,但是如果想要实现精度较高的定时功能的话,就要使用setitimer函数。
setitimer()为Linux的API,并非C语言的Standard Library,setitimer()有两个功能,一是指定一段时间后,才执行某个function,二是每间格一段时间就执行某个function;
Linux为每个任务安排了3个内部定时器:
ITIMER_REAL:实时定时器,不管进程在何种模式下运行(甚至在进程被挂起时),它总在计数。定时到达,向进程发送SIGALRM信号。
ITIMER_VIRTUAL:这个不是实时定时器,当进程在用户模式(即程序执行时)计算进程执行的时间。定时到达后向该进程发送SIGVTALRM信号。
ITIMER_PROF:进程在用户模式(即程序执行时)和核心模式(即进程调度用时)均计数。定时到达产生SIGPROF信号。ITIMER_PROF记录的时间比ITIMER_VIRTUAL多了进程调度所花的时间。
定时器在初始化是,被赋予一个初始值,随时间递减,递减至0后发出信号,同时恢复初始值。在任务中,我们可以一种或者全部三种定时器,但同一时刻同一类型的定时器只能使用一个。
setitimer函数原型如下:
1 #include <sys/time.h> 2 3 int setitimer(int which, const struct itimerval *new_value, 4 struct itimerval *old_value); 5 6 Timer values are defined by the following structures: 7 8 struct itimerval { 9 struct timeval it_interval; /* next value */ 10 struct timeval it_value; /* current value */ 11 }; 12 13 struct timeval { 14 time_t tv_sec; /* seconds */ 15 suseconds_t tv_usec; /* microseconds */ 16 };
it_interval用来指定每隔多长时间执行任务, it_value用来保存当前时间离执行任务还有多长时间。比如说, 你指定it_interval为2秒(微秒为0),开始的时候我们把it_value的时间也设定为2秒(微秒为0),当过了一秒, it_value就减少一个为1, 再过1秒,则it_value又减少1,变为0,这个时候发出信号(告诉用户时间到了,可以执行任务了),并且系统自动把it_value的时间重置为 it_interval的值,即2秒,再重新计数
下面是setitimer简单实例:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <signal.h> 5 #include <sys/time.h> 6 7 void test_func() 8 { 9 static count = 0; 10 11 printf("count is %d ", count++); 12 } 13 14 void init_sigaction() 15 { 16 struct sigaction act; 17 18 act.sa_handler = test_func; //设置处理信号的函数 19 act.sa_flags = 0; 20 21 sigemptyset(&act.sa_mask); 22 sigaction(SIGPROF, &act, NULL);//时间到发送SIGROF信号 23 } 24 25 void init_time() 26 { 27 struct itimerval val; 28 29 val.it_value.tv_sec = 1; //1秒后启用定时器 30 val.it_value.tv_usec = 0; 31 32 val.it_interval = val.it_value; //定时器间隔为1s 33 34 setitimer(ITIMER_PROF, &val, NULL); 35 } 36 37 int main(int argc, char **argv) 38 { 39 40 init_sigaction(); 41 init_time(); 42 43 while(1); 44 45 return 0; 46 }
可以看出每个一秒输出一个count的值:
下面是运行结果:
[root@localhost 5th]# ./test
count is 0
count is 1
count is 2
count is 3
count is 4
count is 5
count is 6
count is 7
count is 8
count is 9