我們常常有設(shè)置系統(tǒng)在某一時間執(zhí)行相應(yīng)動作的需求,比如設(shè)置電腦什么時候自動鎖屏,什么時候自動關(guān)機,設(shè)置應(yīng)用程序什么時候自動運行,什么時候自動退出。這些與時間相關(guān)的功能,都需要依靠操作系統(tǒng)中的定時器來實現(xiàn)。
linux中定時器的使用原理很簡單,你只需設(shè)置一個超時時間和相應(yīng)的執(zhí)行函數(shù),系統(tǒng)就會在超時的時候執(zhí)行一開始設(shè)置的函數(shù)。超時的概念有點模糊,它指的是你設(shè)定一個時間,如果當前的時間超過了你設(shè)定的時間,那就超時了。比如說,你設(shè)置五分鐘后系統(tǒng)自動關(guān)機,系統(tǒng)會記住五分鐘后的具體時間,也就是當前時間再加上五分鐘。過了五分鐘后,系統(tǒng)當前時間已經(jīng)比剛才設(shè)置的具體時間大了,出現(xiàn)超時,于是運行超時行為。
在linux中,使用alarm函數(shù)可以設(shè)置一個定時器,當定時器超時的時候,會產(chǎn)生SIGALRM信號。因此,要設(shè)置超時行為,就得在SIGALRM信號上設(shè)置相應(yīng)的函數(shù)。
包含頭文件:#include <unistd.h>
函數(shù)原型:unsigned int alarm(unsigned int seconds);
具體例子如下:
#include <stdio.h>#include <signal.h> #include <unistd.h>void SigFun(int signo){ PRintf("SigFun is running/n");}int main(){ if(signal(SIGALRM, SigFun) == SIG_ERR){ perror("signal/n"); return -1; } alarm(5); pause();}在linux中,一個進程只能有一個定時器,因此當一個進程需要設(shè)置多個定時行為時,需要采取相應(yīng)的措施,使得一個定時器可以實現(xiàn)多個定時。主要的方法有兩種,一種叫時間鏈,一種叫時間堆。
時間鏈是將所有定時行為以鏈表的方式連在一起,同時在進程中維護一個固定時間超時的定時器。當定時器超時的時候,檢查鏈表上所有的行為是否超時,如果有超時的行為,則運行其行為,并將其從鏈表中刪除。這用方法最大的壞處就是需要固定時間遍歷整個鏈表,造成了比較大的開銷。
時間堆是將所有定時行為以最小堆的方式組織起來,并且在進程中維護一個以堆頂為超時時間的定時器。當定時器超時時,檢查堆頂行為是否超時,如果超時,則運行該行為,并將其從堆頂刪除,接著繼續(xù)檢查;如果堆頂行為未超時,則用其超時時間繼續(xù)設(shè)置定時器。時間堆不用固定時間去檢查所有定時行為,只需在超時的時候運行相應(yīng)的超時行為,效率比時間鏈高。
在linux中,alarm函數(shù)是以秒計時的,當有時我們需要更小的時間單位去設(shè)置行為,比如毫秒,應(yīng)該怎么辦呢?linux提供setitimer函數(shù),可以提供更精確的定時器。
包含頭文件:#include <sys/time.h>
函數(shù)原型:int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
參數(shù):
int which有三種選擇:
ITIMER_REAL:decrements in real time, and deliverssIGALRMupon expiration.
ITIMER_VIRTUAL:decrements only when the process is executing, anddeliversSIGVTALRMupon expiration.
ITIMER_PROF:decrements both when the process executes and when thesystem is executing on behalfof the process.CoupledwithITIMER_VIRTUAL, this timer is usually used to profile the timespent by the application in userand kernel space. SIGPROFis delivered
const struct itimerval *new_value的數(shù)據(jù)結(jié)構(gòu)如下:
struct itimerval { struct timeval it_interval; /* 第一次超時以后每次超時的時間 */ struct timeval it_value; /* 第一次超時的時間 */};struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */};struct itimerval *old_value是原來設(shè)置的時間,如果不需要用到,可以用NULL
成功調(diào)用返回0,失敗返回-1。
具體例子如下:
#include <stdio.h>#include <signal.h>#include <unistd.h>#include <sys/time.h>void SigFun(int signo){ printf("SigFun is running/n"); }int main(){ if(signal(SIGALRM, SigFun) == SIG_ERR){ perror("signal/n"); return -1; } struct itimerval tv; tv.it_value.tv_usec = 500000; tv.it_value.tv_sec = 0; tv.it_interval.tv_usec = 300000; tv.it_interval.tv_sec = 0; if(setitimer(ITIMER_REAL, &tv, NULL) != 0){ perror("setitimer/n"); return -1; } while(true){ pause(); }}新聞熱點
疑難解答
圖片精選