使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务。要达到这一目的,通常有两个常见的比较有效的方法。一 个是用linux内部的三个定时器,另外一个是用sleep, usleep函数让进程睡眠一段时间,使用alarm定时发出一个信号,还有那就是用gettimeofday, difftime等本身来计算时间间隔,而后时间到了就执行某一任务,可是这种方法效率低,因此不经常使用。linux
alarm用在不须要经肯定时的时候,返回以前剩余的秒数。函数
NAME
alarm - set an alarm clock for delivery of a signal
SYNOPSIS
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
DESCRIPTION
alarm arranges for a SIGALRM signal to be delivered to the process in
seconds seconds.
If seconds is zero, no new alarm is scheduled.
In any event any previously set alarm is cancelled. 测试
测试程序:spa
1 | cat timer.c |
2 | #include <stdio.h> |
3 | #include <unistd.h> |
4 | #include <sys/time.h> |
5 | #include <signal.h> |
6 | |
7 | void func() |
8 | { |
9 | printf("2 s reached.\n"); |
10 | } |
11 | |
12 | int main() |
13 | { |
14 | signal(SIGALRM,func); |
15 | alarm(2); |
16 | while(1); |
17 | return 0; |
18 | } |
19 |
Linux为每一个任务安排了3个内部定时器: 进程
ITIMER_REAL:实时定时器,无论进程在何种模式下运行(甚至在进程被挂起时),它总在计数。定时到达,向进程发送SIGALRM信号。 ip
ITIMER_VIRTUAL:这个不是实时定时器,当进程在用户模式(即程序执行时)计算进程执行的时间。定时到达后向该进程发送SIGVTALRM信号。 ci
ITIMER_PROF:进程在用户模式(即程序执行时)和核心模式(即进程调度用时)均计数。定时到达产生SIGPROF信号。ITIMER_PROF记录的时间比ITIMER_VIRTUAL多了进程调度所花的时间。 字符串
定时器在初始化是,被赋予一个初始值,随时间递减,递减至0后发出信号,同时恢复初始值。在任务中,咱们能够一种或者所有三种定时器,但同一时刻同一类型的定时器只能使用一个。 get
用到的函数有: string
#include <sys/time.h>
int getitimer(int which, struct itimerval *value);
int setitimer(int which, struct itimerval*newvalue, struct itimerval* oldvalue);
strcut timeval
{
long tv_sec; /*秒*/
long tv_usec; /*微秒*/
};
struct itimerval
{
struct timeval it_interval; /*时间间隔*/
struct timeval it_value; /*当前时间计数*/
};
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秒,再从新计数。
为了帮助你理解这个问题,咱们来看一个例子:
1 | #include <stdio.h> |
2 | #include <signal.h> |
3 | #include <sys/time.h> |
4 | |
5 | /* |
6 | ******************************************************************************************************* |
7 | ** Function name: main() |
8 | ** Descriptions : Demo for timer. |
9 | ** Input : NONE |
10 | ** Output : NONE |
11 | ** Created by : Chenxibing |
12 | ** Created Date : 2005-12-29 |
13 | **----------------------------------------------------------------------------------------------------- |
14 | ** Modified by : |
15 | ** Modified Date: |
16 | **----------------------------------------------------------------------------------------------------- |
17 | ******************************************************************************************************* |
18 | */ |
19 | int limit = 10; |
20 | /* signal process */ |
21 | void timeout_info(int signo) |
22 | { |
23 | if(limit == 0) |
24 | { |
25 | printf("Sorry, time limit reached.\n"); |
26 | return; |
27 | } |
28 | printf("only %d senconds left.\n", limit--); |
29 | } |
30 | |
31 | /* init sigaction */ |
32 | void init_sigaction(void) |
33 | { |
34 | struct sigaction act; |
35 | |
36 | act.sa_handler = timeout_info; |
37 | act.sa_flags = 0; |
38 | sigemptyset(&act.sa_mask); |
39 | sigaction(SIGPROF, &act, NULL); |
40 | } |
41 | |
42 | /* init */ |
43 | void init_time(void) |
44 | { |
45 | struct itimerval val; |
46 | |
47 | val.it_value.tv_sec = 1; |
48 | val.it_value.tv_usec = 0; |
49 | val.it_interval = val.it_value; |
50 | setitimer(ITIMER_PROF, &val, NULL); |
51 | } |
52 | |
53 | |
54 | int main(void) |
55 | { |
56 | init_sigaction(); |
57 | init_time(); |
58 | printf("You have only 10 seconds for thinking.\n"); |
59 | |
60 | while(1); |
61 | return 0; |
62 | } |
63 |
对 于ITIMER_VIRTUAL和ITIMER_PROF的使用方法相似,当你在setitimer里面设置的定时器为ITIMER_VIRTUAL的时 候,你把sigaction里面的SIGALRM改成SIGVTALARM, 同理,ITIMER_PROF对应SIGPROF。
不过,你可能会注意到,当你用ITIMER_VIRTUAL和ITIMER_PROF的时候,你拿一个秒表,你会发现程序输出字符串的时间间隔会不止2秒,甚至5-6秒才会输出一个,至于为何,本身好好琢磨一下^_^
下面咱们来看看用sleep以及usleep怎么实现定时执行任务。
看到了吧,这个要比上面的简单多了,并且你用秒表测一下,时间很准,指定2秒到了就给你输出一个字符串。因此,若是你只作通常的定时,到了时间去执行一个任务,这种方法是最简单的。
下面咱们来看看,经过本身计算时间差的方法来定时:
这个和上面不一样之处在于,是本身手工计算时间差的,若是你想更精确的计算时间差,你能够把 time 函数换成gettimeofday,这个能够精确到微妙。
上面介绍的几种定时方法各有千秋,在计时效率上、方法上和时间的精确度上也各有不一样,采用哪一种方法,就看你程序的须要。