原創博文,轉載請標明出處--周學偉http://www.cnblogs.com/zxouxuewei/linux
linux操做系統爲每個進程提供了3個內部計時器。函數
ITIMER_REAL;ITIMER_VIRTUAL;ITIMER_PROF.spa
ITIMER_REAL:給定一個指定的時間間隔,按照實際的時間來減小這個計數,當時間間隔爲0的時候發出SIGALRM信號。操作系統
ITIMER_VIRTUAL:給定一個時間間隔,當進程執行的時候才減小計數,時間間隔爲0的時候發出SIGVTALRM信號。指針
ITIMER_PROF:給定一個時間間隔,當進程執行或者是系統爲進程調度的時候,減小計數,時間到了,發出SIGPROF信號,這個和TIMER_VIRTUAL聯合,經常使用來計算系統內核時間和用戶時間。rest
看一下getitimer的數據手冊code
getitimer, setitimer - get or set value of an interval timerblog
#include <sys/time.h>進程
int getitimer(int which, struct itimerval *value);get
int setitimer(int which, char struct itimerval *value, struct itimerval *ovalue);
ITIMER_REAL;ITIMER_VIRTUAL;ITIMER_PROF.就是三個定時器,在使用的時候,當其中的任何一個時間到了,都會給進程發送一個信號,而後定時器從新被裝填,從新開始定時動做。
它們對應的信號
ITIMER_REAL ---- SIGALRM
ITIMER_VIRTUAL ---- SIGVTALRM
ITIMER_PROF ---- SIGPROF
函數中的which就是選擇這三個定時器中的一個。
下面是描述時間結構體value的
struct itimerval {
struct timeval it_interval; //下一個值
struct timeval it_value; //當前的值
};
struct timeval {
long tv_sec; //秒
long tv_usec; //毫秒
};
一個表示時間的結構體,一個含有時間結構體的結構體。
使用定時器的時候,首先定義一個時間結構體,而後初始化這個時間結構體的秒和毫秒。而後使用setitimer函數,第一個參數指定使用哪個定時器,第二個參數就是傳遞進去的時間結構體,第三個參數爲NULL。這樣就設定好了一個定時器了。它就能夠開始工做了。
說一下返回值: 函數調用成功返回0, 錯誤返回-1,而且設置出錯值errno。
當出錯的時候:多是value或者是ovalue指針無效;或者是定時器搞錯了,不是這三個中的一個;或者是時間結構體中的毫秒超出了0到999999的範圍。
因爲當定時器的時間到了的時候會引起一個信號,所以咱們必須對信號進行處理,所以須要瞭解一下信號處理的函數。
咱們能夠修改linux系統信號的相關聯的動做,也就是當捕獲到某個信號時須要執行什麼函數。有點像是能夠更改函數指針指向的函數同樣。
有這麼一個函數能夠完成這個問題:sigaction。
也就是sig-action,signal-action,信號動做。
#include<sginal.h>
int sigaction(int signo, const struct sigacton *rstrict act, struct sigaction *restrict oact);
這個函數具備三個參數,第一個是信號的名字,直接寫系統的信號名,好比SIGALRM之類的。第二個參數是一個結構體,表述了信號相關的東西,咱們 修改的函數指針就在裏面。第三個函數是用來返回的,返回該信號的上一個動做,也就是上一個這個信號結構體裏面的函數指針指向的函數。
下面看一下這個信號結構體。
struct sigaction {
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
void (*sa_sigaction)(int, siginfo_t *, void *);
};
在使用的時候,sa_handler和sa_sigaction只是用一個。
sa_mask是和sa_handler一塊兒的。
sa_mask表示了一個信號集合,在調用sigaction以前要先用sigemptyset把sa_mask加入到進程的信號屏蔽字當中。
sigemptyset函數初始化一個sigset_t *類型的信號集合,清除裏面的全部信號。
使用函數sigaction(SIGALRM, &tact, NULL)就是把SIGALRM的信號的觸發動做變成tact結構體中的sa_handler或者sa_sigaction所指向的函數了。
例子以下,每隔2秒鐘打印一行字。
一個函數用來設置信號相關的函數綁定,一個函數用來初始化定時器而且啓動它。
而後程序須要運行好久,放到死循環裏面去,才能看出來效果,通常的應用程序,都不會自動退出的,每每是永遠不退出,或者是等待用戶關閉它。
#include<sys/time.h> #include<stdio.h> #include<unistd.h> #include<signal.h> #include<string.h> static char msg[] = "time is running out./n"; static int len; void prompt_info(int signo) { write(STDERR_FILENO, msg, len); } void init_sigaction(void) { struct sigaction tact; tact.sa_handler = prompt_info; tact.sa_flags = 0; sigemptyset(&tact.sa_mask); sigaction(SIGALRM, &tact, NULL); } 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_REAL, &value, NULL); } int main() { len = strlen(msg); init_sigaction(); init_time(); while(1); exit(0); }