setitimer
Linux 為每一個進程提供了 3 個 setitimer 間隔計時器:
- ITIMER_REAL:減少實際時間,到期的時候發出 SIGALRM 信號。
- ITIMER_VIRTUAL:減少有效時間 (進程執行的時間),產生 SIGVTALRM 信號。
- ITIMER_PROF:減少進程的有效時間和系統時間 (為進程調度用的時間)。這個經常和上面一個使用用來計算系統內核時間和用戶時間。產生 SIGPROF 信號。
所謂 REAL 時間,即我們人類自然感受的時間,英文計算機文檔中也經常使用 wall-clock 這個術語。說白了就是我們通常所說的時間,比如現在是下午 5 點 10 分,那么一分鐘的 REAL 時間之后就是下午 5 點 11 分。
VIRTUAL 時間是進程執行的時間,Linux 是一個多用戶多任務系統,在過去的 1 分鐘內,指定進程實際在 CPU 上的執行時間往往并沒有 1 分鐘,因為其他進程會被 Linux 調度執行,在那些時間內,雖然自然時間在流逝,但指定進程并沒有真正的運行。VIRTUAL 時間就是指定進程真正的有效執行時間。比如 5 點 10 分開始的 1 分鐘內,進程 P1 被 Linux 調度并占用 CPU 的執行時間為 30 秒,那么 VIRTUAL 時間對于進程 P1 來講就是 30 秒。此時自然時間已經到了 5 點 11 分,但從進程 P1 的眼中看來,時間只過了 30 秒。
PROF 時間比較獨特,對進程 P1 來說從 5 點 10 分開始的 1 分鐘內,雖然自己的執行時間為 30 秒,但實際上還有 10 秒鐘內核是在執行 P1 發起的系統調用,那么這 10 秒鐘也被加入到 PROF 時間。這種時間定義主要用于全面衡量進程的性能,因為在統計程序性能的時候,10 秒的系統調用時間也應該算到 P1 的頭上。這也許就是 PROF 這個名字的來歷吧。
使用 setitimer Timer 需要了解下面這些接口 API:
int getitimer(int which,struct itimerval *value); int setitimer(int which,struct itimerval *newval, struct itimerval *oldval);
itimerval 的定義如下:
struct itimerval { struct timeval it_interval; struct timeval it_value; }
getitimer 函數得到間隔計時器的時間值,保存在 value 中。
setitimer 函數設置間隔計時器的時間值為 newval. 并將舊值保存在 oldval 中;which 表示使用三個計時器中的哪一個。
itimerval 結構中的 it_value 是第一次調用后觸發定時器的時間,當這個值遞減為 0 時,系統會向進程發出相應的信號。此后將以 it_internval 為周期定時觸發定時器。
給出一個具體的例子:
清單 9,setitmer 例子
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
void print_info(int signo)
{
?printf("timer fired\n");//簡單的打印,表示 timer 到期
}
void init_sigaction(void)
{
?struct sigaction act;
?act.sa_handler= print_info;
?act.sa_flags=0;
?sigemptyset(&act.sa_mask);
?sigaction(SIGPROF,&act,NULL); //設置信號 SIGPROF 的處理函數為 print_info
}
void init_time()
{
?struct itimerval value;
?value.it_value.tv_sec=2;
?value.it_value.tv_usec=0;
?value.it_interval=value.it_value;
?setitimer(ITIMER_PROF,&value,NULL); //初始化 timer,到期發送 SIGPROF 信號
}
int main()
{
?init_sigaction();
?init_time();
?while(1);
?return 0;
}
這個程序使用 PROF 時間,每經過兩秒 PROF 時間之后就會打印一下 timer fired
字符串。
需要指出:setitimer 計時器的精度為 ms,即 1000 分之 1 秒,足以滿足絕大多數應用程序的需要。但多媒體等應用可能需要更高精度的定時,那么就需要考慮使用下一類定時器:POSIX Timer。