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\n"); 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\n", 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