• <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

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

            alarm

            alarm用在不需要經(jīng)確定時(shí)的時(shí)候,返回之前剩余的秒數(shù)。

            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內(nèi)置的3個(gè)定時(shí)器

            Linux為每個(gè)任務(wù)安排了3個(gè)內(nèi)部定時(shí)器:

            ITIMER_REAL:實(shí)時(shí)定時(shí)器,不管進(jìn)程在何種模式下運(yùn)行(甚至在進(jìn)程被掛起時(shí)),它總在計(jì)數(shù)。定時(shí)到達(dá),向進(jìn)程發(fā)送SIGALRM信號。

            ITIMER_VIRTUAL:這個(gè)不是實(shí)時(shí)定時(shí)器,當(dāng)進(jìn)程在用戶模式(即程序執(zhí)行時(shí))計(jì)算進(jìn)程執(zhí)行的時(shí)間。定時(shí)到達(dá)后向該進(jìn)程發(fā)送SIGVTALRM信號。 

            ITIMER_PROF:進(jìn)程在用戶模式(即程序執(zhí)行時(shí))和核心模式(即進(jìn)程調(diào)度用時(shí))均計(jì)數(shù)。定時(shí)到達(dá)產(chǎn)生SIGPROF信號。ITIMER_PROF記錄的時(shí)間比ITIMER_VIRTUAL多了進(jìn)程調(diào)度所花的時(shí)間。

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

             

            用到的函數(shù)有:

            #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; /*時(shí)間間隔*/
            struct timeval it_value;   /*當(dāng)前時(shí)間計(jì)數(shù)*/
            };

            it_interval用來指定每隔多長時(shí)間執(zhí)行任務(wù), it_value用來保存當(dāng)前時(shí)間離執(zhí)行任務(wù)還有多長時(shí)間。比如說, 你指定it_interval為2秒(微秒為0),開始的時(shí)候我們把it_value的時(shí)間也設(shè)定為2秒(微秒為0),當(dāng)過了一秒, it_value就減少一個(gè)為1, 再過1秒,則it_value又減少1,變?yōu)?,這個(gè)時(shí)候發(fā)出信號(告訴用戶時(shí)間到了,可以執(zhí)行任務(wù)了),并且系統(tǒng)自動把it_value的時(shí)間重置為it_interval的值,即2秒,再重新計(jì)數(shù)。

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

            #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的使用方法類似,當(dāng)你在setitimer里面設(shè)置的定時(shí)器為ITIMER_VIRTUAL的時(shí)候,你把sigaction里面的SIGALRM改為SIGVTALARM, 同理,ITIMER_PROF對應(yīng)SIGPROF。

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

            sleep

            下面我們來看看用sleep以及usleep怎么實(shí)現(xiàn)定時(shí)執(zhí)行任務(wù)。

            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. /*向主進(jìn)程發(fā)送信號,實(shí)際上是自己給自己發(fā)信號*/
            24. sigqueue(getpid(), 50, tsval);
            25. }
            26. return 0;
            27. }

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

            時(shí)間差

            下面我們來看看,通過自己計(jì)算時(shí)間差的方法來定時(shí):

             

            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. /*獲取當(dāng)前時(shí)間*/
            27. time(&nowtime);
            28. /*和上一次的時(shí)間做比較,如果大于等于2秒,則立刻發(fā)送信號*/
            29. if (nowtime - lasttime >= 2)
            30. {
            31. /*向主進(jìn)程發(fā)送信號,實(shí)際上是自己給自己發(fā)信號*/
            32. sigqueue(getpid(), 50, tsval);
            33. lasttime = nowtime;
            34. }
            35. }
            36. return 0;
            37. }

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

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

            posted on 2012-01-31 09:47 老馬驛站 閱讀(9071) 評論(0)  編輯 收藏 引用 所屬分類: c++linux
            热综合一本伊人久久精品| 亚洲精品99久久久久中文字幕| 偷窥少妇久久久久久久久| 97精品国产97久久久久久免费| 久久免费的精品国产V∧| 国产一区二区三区久久| 狠狠精品干练久久久无码中文字幕 | 久久精品国产精品亚洲精品 | 伊人久久无码精品中文字幕| 久久精品免费一区二区| 久久99精品国产99久久6男男| 国产精品一区二区久久精品无码 | 欧美黑人激情性久久| 国产亚洲精午夜久久久久久| 久久久久亚洲精品日久生情| Xx性欧美肥妇精品久久久久久| 久久久久99这里有精品10| 国产精品久久成人影院| 久久这里的只有是精品23| 久久99国产精品久久久| 麻豆AV一区二区三区久久| 武侠古典久久婷婷狼人伊人| 国产精品一久久香蕉国产线看 | 亚洲国产成人久久综合一| 亚洲av日韩精品久久久久久a | 中文字幕亚洲综合久久| 欧美黑人激情性久久| 久久久久高潮综合影院| 日韩中文久久| 久久久久久无码国产精品中文字幕 | 久久综合给合综合久久| 色综合色天天久久婷婷基地| 热re99久久6国产精品免费| 亚洲精品无码久久久久| 亚洲中文字幕无码久久精品1 | 香蕉久久夜色精品国产小说| 99久久中文字幕| 精品综合久久久久久97超人 | 国产精品久久久久aaaa| 久久99热只有频精品8| 97久久久久人妻精品专区|