• <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
            久久久久亚洲AV无码专区体验| 99久久99久久| 午夜天堂精品久久久久| 国产精品一区二区久久| 久久艹国产| 色欲久久久天天天综合网| 日本精品久久久久中文字幕| 久久夜色精品国产噜噜亚洲a| 久久精品人人做人人妻人人玩 | 久久这里只精品国产99热| 色综合久久88色综合天天 | 久久精品无码专区免费青青| 久久精品中文字幕有码| 99久久免费国产精精品| 亚洲中文字幕久久精品无码喷水| 很黄很污的网站久久mimi色| 三上悠亚久久精品| 免费无码国产欧美久久18| 久久国产香蕉视频| 久久久久久综合一区中文字幕| 久久精品极品盛宴观看| 国内精品久久久久久久coent| 97久久国产亚洲精品超碰热| 久久久精品久久久久影院| 久久久久人妻精品一区三寸蜜桃 | 久久久久亚洲精品男人的天堂| 国内精品久久久久影院日本| 99久久精品免费看国产一区二区三区| 久久精品不卡| 国产香蕉97碰碰久久人人| 99久久精品国产毛片| 久久久久国产一级毛片高清版| 久久久久久久久久久久中文字幕| 思思久久精品在热线热| 国产精品久久婷婷六月丁香| 亚洲国产天堂久久久久久 | 久久久久久久99精品免费观看| 国产Av激情久久无码天堂| 久久99精品久久久久久| 久久亚洲国产午夜精品理论片| 日本免费久久久久久久网站|