使用定時器的目的無非是為了周期性的執行某一任務,或者是到了一個指定時間去執行某一個任務。要達到這一目的,一般有兩個常見的比較有效的方法。一個是用linux内部的三個定時器,另一個是用sleep, usleep函數讓程序睡眠一段時間,使用alarm定時發出一個信号,還有那就是用gettimeofday, difftime等自己來計算時間間隔,然後時間到了就執行某一任務,但是這種方法效率低,是以不常用。
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.
測試程式:
1
cat timer.<b>c</b>
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(<b>2</b>);
16
while(<b>1</b>);
17
return <b>0</b>;
18
19
Linux為每個任務安排了3個内部定時器:
ITIMER_REAL:實時定時器,不管程序在何種模式下運作(甚至在程序被挂起時),它總在計數。定時到達,向程序發送SIGALRM信号。
ITIMER_VIRTUAL:這個不是實時定時器,當程序在使用者模式(即程式執行時)計算程序執行的時間。定時到達後向該程序發送SIGVTALRM信号。
ITIMER_PROF:程序在使用者模式(即程式執行時)和核心模式(即程序排程用時)均計數。定時到達産生SIGPROF信号。ITIMER_PROF記錄的時間比ITIMER_VIRTUAL多了程序排程所花的時間。
定時器在初始化是,被賦予一個初始值,随時間遞減,遞減至0後發出信号,同時恢複初始值。在任務中,我們可以一種或者全部三種定時器,但同一時刻同一類型的定時器隻能使用一個。
用到的函數有:
#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秒,再重新計數。
為了幫助你了解這個問題,我們來看一個例子:
/*
*******************************************************************************************************
** Function name: main()
** Descriptions : Demo for timer.
** Input : NONE
** Output : NONE
** Created by : Chenxibing
** Created Date : <b>2005</b>-<b>12</b>-<b>29</b>
**-----------------------------------------------------------------------------------------------------
** Modified by :
** Modified Date:
*/
int limit = <b>10</b>;
20
/* signal process */
21
void timeout_info(int signo)
22
23
if(limit == <b>0</b>)
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 = <b>0</b>;
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 = <b>1</b>;
48
val.it_value.tv_usec = <b>0</b>;
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(<b>1</b>);
61
return <b>0</b>;
62
63
對于ITIMER_VIRTUAL和ITIMER_PROF的使用方法類似,當你在setitimer裡面設定的定時器為ITIMER_VIRTUAL的時候,你把sigaction裡面的SIGALRM改為SIGVTALARM, 同理,ITIMER_PROF對應SIGPROF。
不過,你可能會注意到,當你用ITIMER_VIRTUAL和ITIMER_PROF的時候,你拿一個秒表,你會發現程式輸出字元串的時間間隔會不止2秒,甚至5-6秒才會輸出一個,至于為什麼,自己好好琢磨一下^_^
下面我們來看看用sleep以及usleep怎麼實作定時執行任務。
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
static char msg[] = "I received a msg.\n";
int len;
void show_msg(int signo)
write(STDERR_FILENO, msg, len);
int main()
struct sigaction act;
union sigval tsval;
act.sa_handler = show_msg;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(50, &act, NULL);
len = strlen(msg);
while ( 1 )
sleep(2); /*睡眠2秒*/
/*向主程序發送信号,實際上是自己給自己發信号*/
sigqueue(getpid(), 50, tsval);
return 0;
看到了吧,這個要比上面的簡單多了,而且你用秒表測一下,時間很準,指定2秒到了就給你輸出一個字元串。是以,如果你隻做一般的定時,到了時間去執行一個任務,這種方法是最簡單的。
下面我們來看看,通過自己計算時間差的方法來定時:
#include <time.h>
static time_t lasttime;
time(&lasttime);
time_t nowtime;
/*擷取目前時間*/
time(&nowtime);
/*和上一次的時間做比較,如果大于等于2秒,則立刻發送信号*/
if (nowtime - lasttime >= 2)
lasttime = nowtime;
這個和上面不同之處在于,是自己手工計算時間差的,如果你想更精确的計算時間差,你可以把 time 函數換成gettimeofday,這個可以精确到微妙。
上面介紹的幾種定時方法各有千秋,在計時效率上、方法上和時間的精确度上也各有不同,采用哪種方法,就看你程式的需要。
本文轉自feisky部落格園部落格,原文連結:http://www.cnblogs.com/feisky/archive/2010/03/20/1690561.html,如需轉載請自行聯系原作者