• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-167  評論-8  文章-0  trackbacks-0

            使用定時器的目的無非是為了周期性的執行某一任務,或者是到了一個指定時間去執行某一個任務。要達到這一目的,一般有兩個常見的比較有效的方法。一個是用linux內部的三個定時器,另一個是用sleep, usleep函數讓進程睡眠一段時間,使用alarm定時發出一個信號,還有那就是用gettimeofday, difftime等自己來計算時間間隔,然后時間到了就執行某一任務,但是這種方法效率低,所以不常用。

            alarm

            alarm用在不需要經確定時的時候,返回之前剩余的秒數。

            NAME
                   alarm - set an alarm clock for delivery of a signal
            SYNOPSIS
                   #include <unistd.h>
                   unsigned int alarm(unsigned int seconds);
            DESCRIPTION
                   alarm  arranges  for a SIGALRM signal to be delivered to the process in
                   seconds seconds.
                   If seconds is zero, no new alarm is scheduled.
                   In any event any previously set alarm is cancelled.

            測試程序:

             cat timer.c
            #include <stdio.h>
            #include <unistd.h>
            #include <sys/time.h>
            #include <signal.h>
             
            void func()
            {
                    printf("2 s reached.\n");
            10 }
            11  
            12 int main()
            13 {
            14         signal(SIGALRM,func);
            15         alarm(2);
            16         while(1);
            17         return 0;
            18 }
            19  

            Linux內置的3個定時器

            Linux為每個任務安排了3個內部定時器:

            ITIMER_REAL:實時定時器,不管進程在何種模式下運行(甚至在進程被掛起時),它總在計數。定時到達,向進程發送SIGALRM信號。

            ITIMER_VIRTUAL:這個不是實時定時器,當進程在用戶模式(即程序執行時)計算進程執行的時間。定時到達后向該進程發送SIGVTALRM信號。 

            ITIMER_PROF:進程在用戶模式(即程序執行時)和核心模式(即進程調度用時)均計數。定時到達產生SIGPROF信號。ITIMER_PROF記錄的時間比ITIMER_VIRTUAL多了進程調度所花的時間。

            定時器在初始化是,被賦予一個初始值,隨時間遞減,遞減至0后發出信號,同時恢復初始值。在任務中,我們可以一種或者全部三種定時器,但同一時刻同一類型的定時器只能使用一個。

             

            用到的函數有:

            #include <sys/time.h>
            int getitimer(int which, struct itimerval *value);
            int setitimer(int which, struct itimerval*newvalue, struct itimerval* oldvalue);
            strcut timeval
            {
            long tv_sec; /*秒*/
            long tv_usec; /*微秒*/
            };
            struct itimerval
            {
            struct timeval it_interval; /*時間間隔*/
            struct timeval it_value;   /*當前時間計數*/
            };

            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秒,再重新計數。

            為了幫助你理解這個問題,我們來看一個例子:

            #include <stdio.h>
            #include <signal.h>
            #include <sys/time.h>
             
            /*
            *******************************************************************************************************
            ** Function name: main()
            ** Descriptions : Demo for timer.
            ** Input        : NONE
            10 ** Output       : NONE
            11 ** Created by   : Chenxibing
            12 ** Created Date : 2005-12-29
            13 **-----------------------------------------------------------------------------------------------------
            14 ** Modified by  :
            15 ** Modified Date:
            16 **-----------------------------------------------------------------------------------------------------
            17 *******************************************************************************************************
            18 */
            19 int limit = 10;
            20 /* signal process */
            21 void timeout_info(int signo)
            22 {
            23     if(limit == 0)
            24     {
            25         printf("Sorry, time limit reached.\n");
            26         return;
            27     }
            28     printf("only %d senconds left.\n", limit--);
            29 }
            30  
            31 /* init sigaction */
            32 void init_sigaction(void)
            33 {
            34     struct sigaction act;
            35  
            36     act.sa_handler = timeout_info;
            37     act.sa_flags   = 0;
            38     sigemptyset(&act.sa_mask);
            39     sigaction(SIGPROF, &act, NULL);
            40 }
            41  
            42 /* init */
            43 void init_time(void)
            44 {
            45     struct itimerval val;
            46  
            47     val.it_value.tv_sec = 1;
            48     val.it_value.tv_usec = 0;
            49     val.it_interval = val.it_value;
            50     setitimer(ITIMER_PROF, &val, NULL);
            51 }
            52  
            53  
            54 int main(void)
            55 {
            56     init_sigaction();
            57     init_time();
            58     printf("You have only 10 seconds for thinking.\n");
            59  
            60     while(1);
            61    return 0;
            62 }
            63  

            對于ITIMER_VIRTUAL和ITIMER_PROF的使用方法類似,當你在setitimer里面設置的定時器為ITIMER_VIRTUAL的時候,你把sigaction里面的SIGALRM改為SIGVTALARM, 同理,ITIMER_PROF對應SIGPROF。

            不過,你可能會注意到,當你用ITIMER_VIRTUAL和ITIMER_PROF的時候,你拿一個秒表,你會發現程序輸出字符串的時間間隔會不止2秒,甚至5-6秒才會輸出一個,至于為什么,自己好好琢磨一下^_^

            sleep

            下面我們來看看用sleep以及usleep怎么實現定時執行任務。

            1. #include <signal.h>
            2. #include <unistd.h>
            3. #include <string.h>
            4. #include <stdio.h>
            5. static char msg[] = "I received a msg.\n";
            6. int len;
            7. void show_msg(int signo)
            8. {
            9. write(STDERR_FILENO, msg, len);
            10. }
            11. int main()
            12. {
            13. struct sigaction act;
            14. union sigval tsval;
            15. act.sa_handler = show_msg;
            16. act.sa_flags = 0;
            17. sigemptyset(&act.sa_mask);
            18. sigaction(50, &act, NULL);
            19. len = strlen(msg);
            20. while ( 1 )
            21. {
            22. sleep(2); /*睡眠2秒*/
            23. /*向主進程發送信號,實際上是自己給自己發信號*/
            24. sigqueue(getpid(), 50, tsval);
            25. }
            26. return 0;
            27. }

            看到了吧,這個要比上面的簡單多了,而且你用秒表測一下,時間很準,指定2秒到了就給你輸出一個字符串。所以,如果你只做一般的定時,到了時間去執行一個任務,這種方法是最簡單的。

            時間差

            下面我們來看看,通過自己計算時間差的方法來定時:

             

            1. #include <signal.h>
            2. #include <unistd.h>
            3. #include <string.h>
            4. #include <stdio.h>
            5. #include <time.h>
            6. static char msg[] = "I received a msg.\n";
            7. int len;
            8. static time_t lasttime;
            9. void show_msg(int signo)
            10. {
            11. write(STDERR_FILENO, msg, len);
            12. }
            13. int main()
            14. {
            15. struct sigaction act;
            16. union sigval tsval;
            17. act.sa_handler = show_msg;
            18. act.sa_flags = 0;
            19. sigemptyset(&act.sa_mask);
            20. sigaction(50, &act, NULL);
            21. len = strlen(msg);
            22. time(&lasttime);
            23. while ( 1 )
            24. {
            25. time_t nowtime;
            26. /*獲取當前時間*/
            27. time(&nowtime);
            28. /*和上一次的時間做比較,如果大于等于2秒,則立刻發送信號*/
            29. if (nowtime - lasttime >= 2)
            30. {
            31. /*向主進程發送信號,實際上是自己給自己發信號*/
            32. sigqueue(getpid(), 50, tsval);
            33. lasttime = nowtime;
            34. }
            35. }
            36. return 0;
            37. }

            這個和上面不同之處在于,是自己手工計算時間差的,如果你想更精確的計算時間差,你可以把 time 函數換成gettimeofday,這個可以精確到微妙。

            上面介紹的幾種定時方法各有千秋,在計時效率上、方法上和時間的精確度上也各有不同,采用哪種方法,就看你程序的需要。

            posted on 2012-01-31 09:47 老馬驛站 閱讀(9061) 評論(0)  編輯 收藏 引用 所屬分類: c++linux
            精品无码久久久久久久久久| 欧美综合天天夜夜久久| 日本高清无卡码一区二区久久 | 亚洲日本久久久午夜精品| 久久久WWW成人免费精品| 欧美亚洲国产精品久久| 久久国产精品99久久久久久老狼| 国产A级毛片久久久精品毛片| 久久91精品国产91| 色偷偷888欧美精品久久久| 一本久久综合亚洲鲁鲁五月天| 色综合久久无码中文字幕| 99精品伊人久久久大香线蕉| 婷婷久久综合| 国产精品99久久久久久www| 久久精品aⅴ无码中文字字幕不卡| 69SEX久久精品国产麻豆| 久久精品综合网| 久久精品国产亚洲7777| 久久国产精品99久久久久久老狼| 伊人久久精品影院| 久久精品?ⅴ无码中文字幕| 亚洲AV无码1区2区久久| 久久亚洲日韩看片无码| 欧美精品丝袜久久久中文字幕 | 狠狠色丁香婷婷综合久久来 | 久久亚洲国产欧洲精品一| 亚洲精品乱码久久久久久中文字幕| 久久久久国产视频电影| 国内精品久久久久国产盗摄| 成人综合伊人五月婷久久| 色诱久久久久综合网ywww| 伊人久久大香线蕉综合影院首页| 久久久久九国产精品| 97精品国产97久久久久久免费| 狠狠色丁香久久综合五月| 久久人人爽人人爽人人AV | 欧美日韩成人精品久久久免费看| 久久国产精品久久| 青青草原综合久久| 久久久国产精华液|