linux用戶態定時器的使用---19

原創博文,轉載請標明出處--周學偉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);  
}
相關文章
相關標籤/搜索