Linux下定時器的使用及實現秒以下精確定時與休眠

2021-06-18 04:56:58 字數 3706 閱讀 8640

linux下定時器的使用 -- alarm() & setitimer():

1、alarm

-------------------------------------------

如果不要求很精確的話,用alarm()和signal()就夠了

unsigned int alarm(unsigned int seconds)

函式說明: alarm()用來設定訊號sigalrm在經過引數seconds指定的秒數後傳送給目前的程序。如果引數seconds為0,則之前設定的鬧鐘會被取消,並將剩下的時間返回。

返回值: 返回之前鬧鐘的剩餘秒數,如果之前未設鬧鐘則返回0。

alarm()執行後,程序將繼續執行,在後期(alarm以後)的執行過程中將會在seconds秒後收到訊號sigalrm並執行其處理函式。

#include

#include

#include

void sigalrm_fn(int sig)

int main(void)

2、setitimer()

-------------------------------------------

int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue));

setitimer()比alarm功能強大,支援3種型別的定時器:

itimer_real :     以系統真實的時間來計算,它送出sigalrm訊號。

itimer_virtual : -以該程序在使用者態下花費的時間來計算,它送出sigvtalrm訊號。

itimer_prof :     以該程序在使用者態下和核心態下所費的時間來計算,它送出sigprof訊號。

setitimer()第乙個引數which指定定時器型別(上面三種之一);第二個引數是結構itimerval的乙個例項;第三個引數可不做處理。

setitimer()呼叫成功返回0,否則返回-1。

下面是關於setitimer呼叫的乙個簡單示範,在該例子中,每隔一秒發出乙個sigalrm,每隔0.5秒發出乙個sigvtalrm訊號:

#include

#include

#include

#include

#include

#include

int sec;

void sigroutine(int signo)

return;

}int main()

(1) struct itimerval

struct itimerval ;

itimerval:      i   --> interval

val --> value        

itimerval結構中的it_value是減少的時間,當這個值為0的時候就發出相應的訊號了. 然後再將it_value設定為it_interval值.

(2) setitimer()

setitimer()為其所在程序設定乙個定時器,如果itimerval.it_interval不為0(it_interval的兩個域都不為0),則該定時器將持續有效(每隔一段時間就會傳送乙個訊號)

注意:linux訊號機制基本上是從unix系統中繼承過來的。早期unix系統中的訊號機制比較簡單和原始,後來在實踐中暴露出一些問題,因此,把那些建立在早期機制上的訊號叫做"不可靠訊號",訊號值小於sigrtmin(sigrtmin=32,sigrtmax=63)的訊號都是不可靠訊號。這就是"不可靠訊號"的**。它的主要問題是:程序每次處理訊號後,就將對訊號的響應設定為預設動作。在某些情況下,將導致對訊號的錯誤處理;因此,使用者如果不希望這樣的操作,那麼就要在訊號處理函式結尾再一次呼叫signal(),重新安裝該訊號。

linux下如何實現秒以下精確定時與休眠

linux中提供的休眠函式是sleep和alarm,但是他們僅僅提供以秒為單位的休眠,這中休眠有些程序顯然太長了,那麼怎樣才能使程序以更小的時間解析度休眠呢?

我知道的方法有2種,下面就做分別介紹。

第一種方法是使用定時器,linux提供的定時器函式是:

int  setitimer(int which, const struct itimerval *value, struct

itimerval *ovalue);

which指定那種定時器。linux提供3種定時器:

timer_real: 準確定時器,超時會發出sigalrm訊號;

timer_virtual: 虛擬定時器,只記程序時間,所以會根據程序執行時間而變化,不能實現準確定時,超時發出sigvtalrm訊號;

timer_prof: 梗概計時器,它會根據程序時間和系統時間而變化,不能實現準確定時,超時發出sigprof訊號;

在程序中應該捕捉所設定時器會發出的訊號,因為程序收到定時器超時發出的訊號後,預設動作是終止。

value是設定定時器時間,相關結構如下:

struct itimerval ;

struct timeval ;

it_interval指定間隔時間,it_value指定初始定時時間。如果只指定it_value,就是實現一次定時;如果同時指定 it_interval,則超時後,系統會重新初始化it_value為it_interval,實現重複定時;兩者都清零,則會清除定時器。

tv_sec提供秒級精度,tv_usec提供微秒級精度,以值大的為先,注意1s = 1000000ms。

ovalue用來儲存先前的值,常設為null。

如果是以setitimer提供的定時器來休眠,只需阻塞等待定時器訊號就可以了。

第二種方法是使用select來提供精確定時和休眠:

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,

struct timeval *timeout);

n指監視的檔案描述符範圍,通常設為所要select的fd+1,readfds,writefds和exceptfds分別是讀,寫和異常檔案描述符集,timeout為超時時間。

可能用到的關於檔案描述符集操作的巨集有:

fd_clr(int fd, fd_set *set);    清除fd

fd_isset(int fd, fd_set *set);  測試fd是否設定

fd_set(int fd, fd_set *set);     設定fd

fd_zero(fd_set *set);             清空描述符集

我們此時用不到這些巨集,因為我們並不關心檔案描述符的狀態,我們關心的是select超時。所以我們需要把readfds,writefds和exceptfds都設為null,只指定timeout時間就行了。至於n我們可以不關心,所以你可以把它設為任何非負值。實現**如下:

int mssleep(long ms) {

struct timeval tv;

tv.tv_sec = 0;

tv.tv_usec = ms;

return select(0, null, null, null, &tv);

呵呵,怎麼樣,是不是很簡單?

結語:setitimer和select都能實現程序的精確休眠,本文分別對他們進行了簡單介紹,並給出了乙個簡單的給予select的實現。我不推薦使用 setitimer,因為一者linux系統提供的timer有限(每個程序至多能設3個不同型別的timer),再者ssetitimer實現起來沒有 select簡單。

linux下定時器實現

linux定時器 是指在每隔一段時間後就會進行一次相關操作,具有計時性的。核心操作是如下方法 int setitimer int which,const struct itimerval restrict value,struct itimerval restrict ovalue 函式返回的是va...

linux下定時器的使用

linux下定時器的使用主要用到兩個函式 setitimer 和getitimer linux系統給每個程序提供了3個定時器,每個定時器在各自不同的域裡面計數,當任何乙個timer計數結束了,系統就發乙個訊號 signal 給該程序,同時計數器重置。以下是支援的三種計數器形式 1 itimer re...

Linux下定時器的使用

2019獨角獸企業重金招聘python工程師標準 linux下應用層定時器本來有好幾種,大夥可以去搜尋其他帖子部落格,這裡我主要描述我在使用setitimer時候遇到的問題,話不多說,直接上 吧 lock timmer test.cpp include include include include...