Linux timer调用流程图,Linux应用层的定时器Timer使用详解【转】
linux下定時(shí)器的使用-- alarm() & setitimer():
1、alarm
-------------------------------------------
如果不要求很精確的話(huà),用alarm()和signal()就夠了unsigned int alarm(unsigned int seconds)
函數(shù)說(shuō)明: alarm()用來(lái)設(shè)置信號(hào)SIGALRM在經(jīng)過(guò)參數(shù)seconds指定的秒數(shù)后傳送給目前的進(jìn)程。如果參數(shù)seconds為0,則之前設(shè)置的鬧鐘會(huì)被取消,并將剩下的時(shí)間返回。返回值:
返回之前鬧鐘的剩余秒數(shù),如果之前未設(shè)鬧鐘則返回0。alarm()執(zhí)行后,進(jìn)程將繼續(xù)執(zhí)行,在后期(alarm以后)的執(zhí)行過(guò)程中將會(huì)在seconds秒后收到信號(hào)SIGALRM并執(zhí)行其處理函數(shù)。#include
#include
#include
void sigalrm_fn(int sig)
{
printf("alarm!/n");
alarm(2);
return;
}
int main(void)
{
signal(SIGALRM, sigalrm_fn);
alarm(1);
while(1) pause();
}
2、setitimer()
-------------------------------------------
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));
setitimer()比alarm功能強(qiáng)大,支持3種類(lèi)型的定時(shí)器:ITIMER_REAL:
以系統(tǒng)真實(shí)的時(shí)間來(lái)計(jì)算,它送出SIGALRM信號(hào)。ITIMER_VIRTUAL:
-以該進(jìn)程在用戶(hù)態(tài)下花費(fèi)的時(shí)間來(lái)計(jì)算,它送出SIGVTALRM信號(hào)。ITIMER_PROF:
以該進(jìn)程在用戶(hù)態(tài)下和內(nèi)核態(tài)下所費(fèi)的時(shí)間來(lái)計(jì)算,它送出SIGPROF信號(hào)。setitimer()第一個(gè)參數(shù)which指定定時(shí)器類(lèi)型(上面三種之一);第二個(gè)參數(shù)是結(jié)構(gòu)itimerval的一個(gè)實(shí)例;第三個(gè)參數(shù)可不做處理。setitimer()調(diào)用成功返回0,否則返回-1。下面是關(guān)于setitimer調(diào)用的一個(gè)簡(jiǎn)單示范,在該例子中,每隔一秒發(fā)出一個(gè)SIGALRM,每隔0.5秒發(fā)出一個(gè)SIGVTALRM信號(hào):#include
#include
#include
#include
#include
#include
int sec;
void sigroutine(int signo){
switch (signo){
case SIGALRM:
printf("Catch a signal -- SIGALRM /n");
signal(SIGALRM, sigroutine);
break;
case SIGVTALRM:
printf("Catch a signal -- SIGVTALRM /n");
signal(SIGVTALRM, sigroutine);
break;
}
return;
}
int main()
{
struct itimerval value, ovalue, value2;?? ??? ?? //(1)
sec = 5;
printf("process id is %d/n", getpid());
signal(SIGALRM, sigroutine);
signal(SIGVTALRM, sigroutine);
value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 1;
value.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &value, &ovalue);//(2)value2.it_value.tv_sec = 0;
value2.it_value.tv_usec = 500000;
value2.it_interval.tv_sec = 0;
value2.it_interval.tv_usec = 500000;
setitimer(ITIMER_VIRTUAL, &value2, &ovalue);for(;;)
;
}
(1) struct itimerval
struct itimerval {
structtimevalit_interval; /* timer
interval */
struct timeval it_value;??? /* current value */
};
itimerval:?? ?? i?? --> interval
val --> value
itimerval結(jié)構(gòu)中的it_value是減少的時(shí)間,當(dāng)這個(gè)值為0的時(shí)候就發(fā)出相應(yīng)的信號(hào)了.
然后再將it_value設(shè)置為it_interval值.
(2) setitimer()
setitimer()為其所在進(jìn)程設(shè)置一個(gè)定時(shí)器,如果itimerval.it_interval不為0(it_interval的兩個(gè)域都不為0),則該定時(shí)器將持續(xù)有效(每隔一段時(shí)間就會(huì)發(fā)送一個(gè)信號(hào))
注意:Linux信號(hào)機(jī)制基本上是從Unix系統(tǒng)中繼承過(guò)來(lái)的。早期Unix系統(tǒng)中的信號(hào)機(jī)制比較簡(jiǎn)單和原始,后來(lái)在實(shí)踐中暴露出一些問(wèn)題,因此,把那些建立在早期機(jī)制上的信號(hào)叫做"不可靠信號(hào)",信號(hào)值小于SIGRTMIN(SIGRTMIN=32,SIGRTMAX=63)的信號(hào)都是不可靠信號(hào)。這就是"不可靠信號(hào)"的來(lái)源。它的主要問(wèn)題是:進(jìn)程每次處理信號(hào)后,就將對(duì)信號(hào)的響應(yīng)設(shè)置為默認(rèn)動(dòng)作。在某些情況下,將導(dǎo)致對(duì)信號(hào)的錯(cuò)誤處理;因此,用戶(hù)如果不希望這樣的操作,那么就要在信號(hào)處理函數(shù)結(jié)尾再一次調(diào)用signal(),重新安裝該信號(hào)。***********************************
Linux下如何實(shí)現(xiàn)秒以下精確定時(shí)與休眠
linux中提供的休眠函數(shù)是sleep和alarm,但是他們僅僅提供以秒為單位的休眠,這中休眠有些進(jìn)程顯然太長(zhǎng)了,那么怎樣才能使進(jìn)程以更小的時(shí)間分辨率休眠呢?
我知道的方法有2種,下面就做分別介紹。
第一種方法是使用定時(shí)器,Linux提供的定時(shí)器函數(shù)是:
int? setitimer(int which, const struct itimerval *value, struct
itimerval *ovalue);
which指定那種定時(shí)器。Linux提供3種定時(shí)器:
TIMER_REAL:
準(zhǔn)確定時(shí)器,超時(shí)會(huì)發(fā)出SIGALRM信號(hào);
TIMER_VIRTUAL:
虛擬定時(shí)器,只記進(jìn)程時(shí)間,所以會(huì)根據(jù)進(jìn)程執(zhí)行時(shí)間而變化,不能實(shí)現(xiàn)準(zhǔn)確定時(shí),超時(shí)發(fā)出SIGVTALRM信號(hào);
TIMER_PROF:
梗概計(jì)時(shí)器,它會(huì)根據(jù)進(jìn)程時(shí)間和系統(tǒng)時(shí)間而變化,不能實(shí)現(xiàn)準(zhǔn)確定時(shí),超時(shí)發(fā)出SIGPROF信號(hào);
在進(jìn)程中應(yīng)該捕捉所設(shè)定時(shí)器會(huì)發(fā)出的信號(hào),因?yàn)檫M(jìn)程收到定時(shí)器超時(shí)發(fā)出的信號(hào)后,默認(rèn)動(dòng)作是終止。
value是設(shè)置定時(shí)器時(shí)間,相關(guān)結(jié)構(gòu)如下:
struct itimerval {
struct timeval it_interval;
struct timeval it_value;
};
struct timeval {
long tv_sec;
long tv_usec;
};
it_interval指定間隔時(shí)間,it_value指定初始定時(shí)時(shí)間。如果只指定it_value,就是實(shí)現(xiàn)一次定時(shí);如果同時(shí)指定it_interval,則超時(shí)后,系統(tǒng)會(huì)重新初始化it_value為it_interval,實(shí)現(xiàn)重復(fù)定時(shí);兩者都清零,則會(huì)清除定時(shí)器。
tv_sec提供秒級(jí)精度,tv_usec提供微秒級(jí)精度,以值大的為先,注意1s
= 1000000ms。
ovalue用來(lái)保存先前的值,常設(shè)為NULL。
如果是以setitimer提供的定時(shí)器來(lái)休眠,只需阻塞等待定時(shí)器信號(hào)就可以了。
第二種方法是使用select來(lái)提供精確定時(shí)和休眠:
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
n指監(jiān)視的文件描述符范圍,通常設(shè)為所要select的fd+1,readfds,writefds和exceptfds分別是讀,寫(xiě)和異常文件描述符集,timeout為超時(shí)時(shí)間。
可能用到的關(guān)于文件描述符集操作的宏有:
FD_CLR(int fd, fd_set *set);
清除fd
FD_ISSET(int fd, fd_set *set);? 測(cè)試fd是否設(shè)置FD_SET(int fd, fd_set *set);?????設(shè)置fd
FD_ZERO(fd_set *set);???????????? 清空描述符集
我們此時(shí)用不到這些宏,因?yàn)槲覀儾⒉魂P(guān)心文件描述符的狀態(tài),我們關(guān)心的是select超時(shí)。所以我們需要把readfds,writefds和exceptfds都設(shè)為NULL,只指定timeout時(shí)間就行了。至于n我們可以不關(guān)心,所以你可以把它設(shè)為任何非負(fù)值。實(shí)現(xiàn)代碼如下:
int msSleep(long ms) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = ms;
return select(0, NULL, NULL, NULL, &tv);
}
呵呵,怎么樣,是不是很簡(jiǎn)單?
結(jié)語(yǔ):
setitimer和select都能實(shí)現(xiàn)進(jìn)程的精確休眠,本文分別對(duì)他們進(jìn)行了簡(jiǎn)單介紹,并給出了一個(gè)簡(jiǎn)單的給予select的實(shí)現(xiàn)。我不推薦使用setitimer,因?yàn)橐徽週inux系統(tǒng)提供的timer有限(每個(gè)進(jìn)程至多能設(shè)3個(gè)不同類(lèi)型的timer),再者ssetitimer實(shí)現(xiàn)起來(lái)沒(méi)有select簡(jiǎn)單。
總結(jié)
以上是生活随笔為你收集整理的Linux timer调用流程图,Linux应用层的定时器Timer使用详解【转】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: moto linux手机,moto li
- 下一篇: linux 其他常用命令