• <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
            久久精品女人天堂AV麻| 久久亚洲精品人成综合网| 国产成人精品综合久久久| 国产A三级久久精品| 日韩精品久久久肉伦网站| 91亚洲国产成人久久精品| 亚洲Av无码国产情品久久| 亚洲AV无一区二区三区久久| 国产美女久久久| 久久这里只有精品首页| 久久不见久久见免费视频7| 久久精品免费大片国产大片| 久久久婷婷五月亚洲97号色| 久久久久亚洲AV无码专区网站 | 蜜臀av性久久久久蜜臀aⅴ| 久久久久久免费一区二区三区| 激情综合色综合久久综合| 乱亲女H秽乱长久久久| 亚洲国产成人久久综合碰| AV无码久久久久不卡网站下载| 久久婷婷色香五月综合激情| 国产精品欧美亚洲韩国日本久久| 亚洲AV乱码久久精品蜜桃| 久久久久综合国产欧美一区二区| 国产精品久久久久久久久免费| 国产精品久久久香蕉| 久久精品国产99久久丝袜| 青青草原综合久久| 国产精品国色综合久久| 国内精品人妻无码久久久影院导航 | 亚洲综合婷婷久久| 97久久超碰成人精品网站| 亚洲AV无码久久寂寞少妇| 国产免费久久精品99re丫y| 久久青青草原亚洲av无码 | 久久久久久国产精品美女| 久久99精品国产麻豆宅宅| .精品久久久麻豆国产精品| 久久久婷婷五月亚洲97号色| 97久久天天综合色天天综合色hd| 狠狠色婷婷久久一区二区|