LINUX 定時器的實現方式__LINUX

來源:互聯網
上載者:User

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

  首先來看看linux作業系統為每一個進程提供的3個內部計時器。

  ITIMER_REAL: 給一個指定的時間間隔,按照實際的時間來減少這個計數,當時間間隔為0的時候發出SIGALRM訊號

  ITIMER_VIRTUAL: 給定一個時間間隔,當進程執行的時候才減少計數,時間間隔為0的時候發出SIGVTALRM訊號

  ITIMER_PROF: 給定一個時間間隔,當進程執行或者是系統為進程調度的時候,減少計數,時間到了,發出SIGPROF訊號,這個和ITIMER_VIRTUAL聯合,常用來計算系統核心程式的時間和使用者時間。

  用到的函數有:

  #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 <sys/time.h>   #include <stdio.h>   #include <unistd.h>   #include <signal.h>   #include <string.h>   static char msg[] = "time is running out/n";   static int len;   // 向標準錯誤輸出資訊,告訴使用者時間到了   void prompt_info(int signo)   {   write(STDERR_FILENO, msg, len);   }   // 建立訊號處理機制   void init_sigaction(void)   {   struct sigaction tact;   /*訊號到了要執行的任務處理函數為prompt_info*/   tact.sa_handler = prompt_info;   tact.sa_flags = 0;   /*初始化訊號集*/   sigemptyset(&tact.sa_mask);   /*建立訊號處理機制*/   sigaction(SIGALRM, &tact, NULL);   } void init_time()   {   struct itimerval value;   /*設定執行任務的時間間隔為2秒0微秒*/   value.it_value.tv_sec = 2;   value.it_value.tv_usec = 0;   /*設定初始時間計數也為2秒0微秒*/   value.it_interval = value.it_value;   /*設定計時器ITIMER_REAL*/   setitimer(ITIMER_REAL, &value, NULL);   }   int main()   {   len = strlen(msg);   init_sigaction();   init_time();   while ( 1 );   exit(0);   }

      該程式的ITMER_REAL定時器,每隔2秒鐘都會發送一個SIGALRM訊號,當主函數接收到了這個訊號之後,調用訊號處理函數prompt_info在標準錯誤上輸出time is running out這個字串。

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

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

      #include <signal.h>   #include <unistd.h>   #include <string.h>   #include <stdio.h>   static char msg[] = "I received a msg./n";   int len;   void show_msg(int signo)   {   write(STDERR_FILENO, msg, len);   }   int main()   {   struct sigaction act;   union sigval tsval;   act.sa_handler = show_msg;   act.sa_flags = 0;   sigemptyset(&act.sa_mask);   sigaction(50, &act, NULL);   len = strlen(msg);   while ( 1 )   {   sleep(2); /*睡眠2秒*/   /*向主進程發送訊號,實際上是自己給自己發訊號*/   sigqueue(getpid(), 50, tsval);   }   return 0;   }

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

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

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

       #include <signal.h>   #include <unistd.h>   #include <string.h>   #include <stdio.h>   #include <time.h>   static char msg[] = "I received a msg./n";   int len;   static time_t lasttime;   void show_msg(int signo)   {   write(STDERR_FILENO, msg, len);   }   int main()   {   struct sigaction act;   union sigval tsval;   act.sa_handler = show_msg;   act.sa_flags = 0;   sigemptyset(&act.sa_mask);   sigaction(50, &act, NULL);   len = strlen(msg);   time(&lasttime);   while ( 1 )   {   time_t nowtime;   /*擷取目前時間*/   time(&nowtime);   /*和上一次的時間做比較,如果大於等於2秒,則立刻發送訊號*/   if (nowtime - lasttime >= 2)   {   /*向主進程發送訊號,實際上是自己給自己發訊號*/   sigqueue(getpid(), 50, tsval);   lasttime = nowtime;   }   }   return 0;   }

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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.