linux應用層定時器與休眠

2021-04-16 23:44:49 字數 3823 閱讀 2506

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中提供的休眠函式是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訊號;

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

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)

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

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

Linux應用層定時器

alarm會設定乙個定時器,當時間到期後會觸發sigalrm訊號,該訊號可能會打斷系統呼叫的執行,它使用的定時器和setitimer對應的itimer real是同乙個。include include include include include include include include i...

應用層定時器 timerfd

sys timerfd.hint timerfd create int clockid,int flags clock realtime systemwide realtime clock.實時時鐘,真實的時間 clock monotonic 系統啟動後開始計時,從不進行調整和復位,不受系統時鐘修改...

Linux應用層下定時器函式setitimer

1.介紹 在linux下如果定時如果要求不太精確的話,使用alarm 和signal 就行了 精確到秒 但是如果想要實現精度較高的定時功能的話,就要使用setitimer函式。setitimer 為linux的api,並非c語言的standard library,setitimer 有兩個功能,一是...