linux 定時器總結

Linux定時器 setitimer 設置“鬧鐘”
2010-04-12 15:19
下面這個例子顯示了設置鬧鐘的方法。

源代碼是:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
/************關於本文檔********************************************
*filename: setitimer.c
*purpose: 顯示了設置鬧鐘的方法
*
*********************************************************************/
void sigroutine(int signo) {
        switch (signo) {
                case SIGALRM:
                        printf("Catch a signal -- SIGALRM\n");
                        break;
                case SIGVTALRM:
                        printf("Catch a signal -- SIGVTALRM\n");
                        break;
        }
}

int main(int argc, char ** argv) {
        struct itimerval value,ovalue,value2;

        printf("process id is %d\n",getpid());
        signal(SIGALRM, sigroutine);
        signal(SIGVTALRM, sigroutine);

        value.it_value.tv_sec = 1;
        value.it_value.tv_usec = 0;
        value.it_interval.tv_sec = 1;
        value.it_interval.tv_usec = 0;
        setitimer(ITIMER_REAL, &value, &ovalue); /* 這將每隔1秒鐘後產生 SIGALRM 信號 */

        value2.it_value.tv_sec = 0;
        value2.it_value.tv_usec = 500000;
        value2.it_interval.tv_sec = 0;
        value2.it_interval.tv_usec = 500000;
        setitimer(ITIMER_VIRTUAL, &value2, &ovalue); /* 對於在運行的程序,這將每隔0.5秒鐘後產生 SIGVTALRM 信號。在sleep時間內是不產生鬧鐘的 */

        for (;;) ;
}
編譯此程序:
gcc -Wall setitimer.c
運行程序:
./a.out

man setitimer 得到如下內容:
SYNOPSIS
       #include <sys/time.h>

       int getitimer(int which, struct itimerval *value);
       int setitimer(int which, const struct itimerval *value,
                     struct itimerval *ovalue);

DESCRIPTION
       The system provides each process with three interval timers, each decrementing in a distinct time domain. When any timer expires, a
       signal is sent to the process, and the timer (potentially) restarts.

       ITIMER_REAL    decrements in real time, and delivers SIGALRM upon expiration.

       ITIMER_VIRTUAL decrements only when the process is executing, and delivers SIGVTALRM upo expiration.

       ITIMER_PROF    decrements both when the process executes and when the system is executing on behalf of the process.   Coupled with
                      ITIMER_VIRTUAL, this timer is usually used to profile the time spent by the application in user and kernel space.
                      SIGPROF is delivered upon expiration.

       Timer values are defined by the following structures:

            struct itimerval {
                struct timeval it_interval; /* next value */
                struct timeval it_value;    /* current value */
            };
            struct timeval {
                long tv_sec;                /* seconds */
                long tv_usec;               /* microseconds */
            };

       The function getitimer() fills the structure indicated by value with the current setting for the timer indicated by which (one of
       ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF). The element it_value is set to the amount of time remaining on the timer, or zero if
       the timer is disabled. Similarly, it_interval is set to the reset value. The function setitimer() sets the indicated timer to the
       value in value. If ovalue is non-zero, the old value of the timer is stored there.

顯然,我們首先設置it_value時間,這個時間就會自動減少,當減少到0時就會產生ITIMER信號,然後it_value將設置爲it_interval的值重複上述鬧鐘計時過程。因此可以每隔一定時間“鬧鐘”一次。
而鬧鐘信號分爲三種,ITIMER_REAL、ITIMER_VIRTUAL、ITIMER_PROF分別代表了當系統運行時產生鬧鐘、當進程在運行時產生鬧鐘、兩種情況下都會產生。通常情況下,只要我們啓動了程序鬧鐘,ITIMER_REAL計時就一定會持續進行;如果是ITIMER_VIRTUAL則只有在程序在運行時計時,如果你程序裏有sleep之類的調用,則在sleep的時候是不會產生SIGVTALRM鬧鐘的。
比如下面這個代碼將只會產生SIGALRM鬧鐘:

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>

void sigroutine(int signo) {
        switch (signo) {
                case SIGALRM:
                        printf("Catch a signal -- SIGALRM\n");
                        break;
                case SIGVTALRM:
                        printf("Catch a signal -- SIGVTALRM\n");
                        break;
        }
}

int main(int argc, char ** argv) {
        struct itimerval value,ovalue,value2;
        int i = 0;

        printf("process id is %d\n",getpid());
        signal(SIGALRM, sigroutine);
        signal(SIGVTALRM, sigroutine);

        value.it_value.tv_sec = 1;
        value.it_value.tv_usec = 0;
        value.it_interval.tv_sec = 1;
        value.it_interval.tv_usec = 0;
        setitimer(ITIMER_REAL, &value, &ovalue);

        value2.it_value.tv_sec = 0;
        value2.it_value.tv_usec = 500000;
        value2.it_interval.tv_sec = 0;
        value2.it_interval.tv_usec = 500000;
        setitimer(ITIMER_VIRTUAL, &value2, &ovalue);

        for (i = 0; i < 50; i++) {
                usleep(100000);
        }
        return 0;
}



Linux 定時器設置(一)
2010-04-12 17:07
定時器設置
函數alarm設置的定時器只能精確到秒,而以下函數理論上可以精確到微妙:
#include <sys/select.h>
#include <sys/time.h>
int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
函數setitimer可以提供三種定時器,它們相互獨立,任意一個定時完成都將發送定時信號到進程,並且自動重新計時。參數which確定了定時器的類型,如表10-6所示:
表10-6 參數which與定時器類型
取值
含義
信號發送
ITIMER_REAL
定時真實時間,與alarm類型相同。
SIGALRM
ITIMER_VIRT
定時進程在用戶態下的實際執行時間。
SIGVTALRM
ITIMER_PROF
定時進程在用戶態和核心態下的實際執行時間。
SIGPROF
這三種定時器定時完成時給進程發送的信號各不相同,其中ITIMER_REAL類定時器發送SIGALRM信號,ITIMER_VIRT類定時器發送SIGVTALRM信號,ITIMER_REAL類定時器發送SIGPROF信號。
函數alarm本質上設置的是低精確、非重載的ITIMER_REAL類定時器,它只能精確到秒,並且每次設置只能產生一次定時。函數setitimer設置的定時器則不同,它們不但可以計時到微妙(理論上),還能自動循環定時。在一個Unix進程中,不能同時使用alarm和ITIMER_REAL類定時器。
結構itimerval描述了定時器的組成:
struct itimerval
{
    struct tim. it_interval;    /* 下次定時取值 */
    struct tim. it_value;       /* 本次定時設置值 */
}
    結構tim.描述了一個精確到微妙的時間:
struct tim.
{
    long    tv_sec;                 /* 秒(1000000微秒) */
    long    tv_usec;                 /* 微妙 */
}
函數setitimer設置一個定時器,參數value指向一個itimerval結構,該結構決定了設置的定時器信息,結構成員it_value指定首次定時的時間,結構成員it_interval指定下次定時的時間。定時器工作時,先將it_value的時間值減到0,發送一個信號,再將it_value賦值爲it_interval的值,重新開始定時,如此反覆。如果it_value值被設置爲0,則定時器停止定時;如果it_value值不爲0但it_interval值爲0,則定時器在一次定時後終止。
函數setitimer調用成功時返回0,否則返回-1,參數ovalue如果不爲空,返回上次的定時器狀態。
函數getitimer獲取當前的定時器狀態,整型參數which指定了讀取的定時器類型,參數value返回定時器狀態。函數調用成功返回0,否則返回-1。

Linux 定時器設置(二)
2010-04-12 17:13
例1. 設置一個定時器,每2.5秒產生一個SIGALRM信號。
答:將itimerval結構的成員it_interval和成員it_value均賦值爲2.5秒即可:
struct itimerval value;
value.it_value.tv_sec=2;
value.it_value.tv_usec=500000;
value.it_interval.tv_sec=2;
value.it_interval.tv_usec=500000;
setitimer(ITIMER_REAL, &value, NULL);
函數setitimer設置的定時器可以重複定時,無需多次調用。
例2. 設置一個定時器,進程在用戶態下執行1秒鐘後發出首次信號,以後進程每在用戶態下執行3秒鐘,發送一個信號。
答:將itimerval結構的成員it_value均賦值爲1秒,成員it_interval賦值爲3秒即可:
struct itimerval value;
value.it_value.tv_sec=1;
value.it_value.tv_usec=0;
value.it_interval.tv_sec=3;
value.it_interval.tv_usec=0;
setitimer(ITIMER_VIRT, &value, NULL);
例3. 取消一個ITIMER_PROF類定時器。
答:將itimerval結構的成員it_value均賦值爲0秒即可:
struct itimerval value;
value.it_value.tv_sec=1;
value.it_value.tv_usec=0;
setitimer(ITIMER_PROF, &value, NULL);
例4. 設置一個定時1.5秒的真實時間定時器,它僅發送一次信號就自動取消。
答:將itimerval結構的成員it_value均賦值爲1.5秒,成員it_interval賦值爲0秒即可:
struct itimerval value;
value.it_value.tv_sec=1;
value.it_value.tv_usec=500000;
value.it_interval.tv_sec=0;
value.it_interval.tv_usec=0;
setitimer(ITIMER_REAL, &value, NULL);

精確定時器實例

本處設計了一個精確定時器的例子,進程每隔1.5秒數發送定時信號SIGPROF,在接收到信號時將打印定時的次數,用戶可以鍵入CTRL_C或DELETE結束程序,如代碼10-11所示:
代碼10-11 精確定時器實例(節自/code/chapter10/time4.c)
#include <sys/select.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int n = 0;
void timefunc(int sig)                      /* 定時事件代碼 */
{
    fprintf(stderr, "ITIMER_PROF[%d]\n", n++);
}
void main()
{
    struct itimerval value;
    value.it_value.tv_sec=1;                /* 定時1.5秒 */
    value.it_value.tv_usec=500000;
    value.it_interval.tv_sec=1;             /* 定時1.5秒 */
    value.it_interval.tv_usec=500000;
    signal(SIGALRM, timefunc);         /* 捕獲定時信號 */
    setitimer(ITIMER_REAL, &value, NULL);   /* 定時開始 */
    while (1);
}
編譯和運行代碼10-11:
# make time4
        cc -O -o time4 time4.c
# ./time4
ITIMER_PROF[0]
ITIMER_PROF[1]
ITIMER_PROF[2]
ITIMER_PROF[3]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章