ø
ø 《linux系統程式設計》第「10.9 定時器」章節
要在linux中使用定時器,有如下三種方法:
定時器方式
乙個程序允許
使用的數量
通知方式
簡單的鬧鐘 - alarm
1個ø 訊號:
sigalrm
間歇定時器 - setitimer
1個ø 訊號:
sigalrm、sigvtalrm、sigprof
高階定時器 - timer_create
無限制ø 訊號:
可以自己選擇用什麼訊號
ø 啟動執行緒
就不會產生訊號,可以避免慢系統呼叫被訊號中斷的問題
有關慢系統呼叫被訊號中斷的問題可以參考我此前寫的一篇文章《訊號中斷與慢系統呼叫》:
alarm()是最簡單的定時器介面,對該函式的呼叫會在真實時間(real time)seconds秒之後將sigalrm訊號發給呼叫程序。它不能自動重啟(即定時器到後要再次定時,需要再呼叫一次alarm)。
間歇定時器setitimer系統呼叫,他可以提供比alarm()更多的控制。它能夠自動重啟。
linux 為每乙個程序提供了 3 個 setitimer 間隔計時器:
ø itimer_real:減少實際時間,到期的時候發出 sigalrm 訊號。
ø itimer_virtual:減少有效時間 (程序執行的時間),產生 sigvtalrm 訊號。
ø itimer_prof:減少程序的有效時間和系統時間 (為程序排程用的時間)。這個經常和上面乙個使用用來計算系統核心時間和使用者時間。產生 sigprof 訊號。
所謂 real 時間,即我們人類自然感受的時間,英文計算機文件中也經常使用 wall-clock 這個術語。說白了就是我們通常所說的時間,比如現在是下午 5 點 10 分,那麼一分鐘的 real 時間之後就是下午 5 點 11 分。
virtual 時間是程序執行的時間,linux 是乙個多使用者多工系統,在過去的 1 分鐘內,指定程序實際在 cpu 上的執行時間往往並沒有 1 分鐘,因為其他程序會被 linux 排程執行,在那些時間內,雖然自然時間在流逝,但指定程序並沒有真正的執行。virtual 時間就是指定進**正的有效執行時間。比如 5 點 10 分開始的 1 分鐘內,程序 p1 被 linux 排程並占用 cpu 的執行時間為 30 秒,那麼 virtual 時間對於程序 p1 來講就是 30 秒。此時自然時間已經到了 5 點 11 分,但從程序 p1 的眼中看來,時間只過了 30 秒。
prof 時間比較獨特,對程序 p1 來說從 5 點 10 分開始的 1 分鐘內,雖然自己的執行時間為 30 秒,但實際上還有 10 秒鐘核心是在執行 p1 發起的系統呼叫,那麼這 10 秒鐘也被加入到 prof 時間。這種時間定義主要用於全面衡量程序的效能,因為在統計程式效能的時候,10 秒的系統呼叫時間也應該算到 p1 的頭上。這也許就是 prof 這個名字的來歷吧。
間隔定時器 setitimer 有一些重要的缺點,posix timer 對 setitimer 進行了增強,克服了 setitimer 的諸多問題:
ø 首先,乙個程序同一時刻只能有乙個 timer。假如應用需要同時維護多個 interval 不同的計時器,必須自己寫**來維護。這非常不方便。使用 posix timer,乙個程序可以建立任意多個 timer。
ø setitmer 計時器時間到達時,只能使用訊號方式通知使用 timer 的程序,而 posix timer 可以有多種通知方式,比如訊號,或者啟動執行緒。
ø 使用 setitimer 時,通知訊號的類別不能改變:sigalarm,sigprof 等,而這些都是傳統訊號,而不是實時訊號,因此有 timer overrun 的問題;而 posix timer 則可以使用實時訊號。
備註:通過kill –l可以檢視系統支援的所有訊號列表。編號為1 ~ 31的訊號為傳統unix支援的訊號,是不可靠訊號(非實時的),編號為32 ~ 63的訊號是後來擴充的,稱做可靠訊號(實時訊號)。不可靠訊號和可靠訊號的區別在於前者不支援排隊,可能會造成訊號丟失,而後者不會。
ø setimer 的精度是 ms,posix timer 是針對有實時要求的應用所設計的,介面支援 ns 級別的時鐘精度。
表 2. posix timer 函式
函式名
功能描述
timer_create
建立乙個新的 timer;並且指定定時器到時通知機制
timer_delete
刪除乙個 timer
timer_gettime
get the time remaining on a posix.1b interval timer
timer_settime
開始或者停止某個定時器。
timer_getoverrun
獲取丟失的定時通知個數。
使用 posix timer 的基本流程很簡單,首先建立乙個 timer。建立的時候可以指定該 timer 的一些特性,比如 clock id。clock id 即 timer 的種類,可以為下表中的任意一種:
表 3. posix timer clock id
clock id
描述
clock_realtime
settable system-wide real-time clock;
clock_monotonic
nonsettable monotonic clock
clock_process_cputime_id
per-process cpu-time clock
clock_thread_cputime_id
per-thread cpu-time clock
ø clock_realtime 時間是系統儲存的時間,即可以由 date 命令顯示的時間,該時間可以重新設定。比如當前時間為上午 10 點 10 分,timer 打算在 10 分鐘後到時。假如 5 分鐘後,我用 date 命令修改當前時間為 10 點 10 分,那麼 timer 還會再等十分鐘到期,因此實際上 timer 等待了 15 分鐘。假如您希望無論任何人如何修改系統時間,timer 都嚴格按照 10 分鐘的週期進行觸發,那麼就可以使用clock_monotonic。
ø clock_process_cputime_id 的含義與 setitimer 的 itimer_virtual 類似。計時器只記錄當前程序所實際花費的時間;比如還是上面的例子,假設系統非常繁忙,當前程序只能獲得 50%的 cpu 時間,為了讓進**正地執行 10 分鐘,應該到 10 點 30 分才允許 timer 到期。
ø clock_thread_cputime_id 以執行緒為計時實體,當前程序中的某個線**正地執行了一定時間才觸發 timer。
設定到期通知方式
timer_create 的第二個引數 struct sigevent 用來設定定時器到時時的通知方式。該資料結構如下:
清單 10,結構sigevent
struct sigevent ;
其中sigev_notify 表示通知方式,有如下幾種:
表 3. posix timer 到期通知方式
通知方式
描述
sigev_none
定時器到期時不產生通知。。。
sigev_signal
定時器到期時將給程序投遞乙個訊號,sigev_signo 可以用來指定使用什麼訊號。
sigev_thread
定時器到期時將啟動新的執行緒進行需要的處理
sigev_thread_id(僅針對 linux)
定時器到期時將向指定執行緒傳送訊號。
ø 如果採用 sigev_none 方式,使用者必須呼叫timer_gettime 函式主動讀取定時器已經走過的時間。類似輪詢。
ø 如果採用 sigev_signal 方式,使用者可以選擇使用什麼訊號,用 sigev_signo 表示訊號值,比如 sig_alarm。
ø如果使用 sigev_thread 方式,則需要設定 sigev_notify_function,當 timer 到期時,將使用該函式作為入口啟動乙個執行緒來處理訊號;sigev_value 儲存了傳入 sigev_notify_function 的引數。sigev_notify_attributes 如果非空,則應該是乙個指向 pthread_attr_t 的指標,用來設定執行緒的屬性(比如 stack 大小,detach 狀態等)。
ø sigev_thread_id 通常和 sigev_signal 聯合使用,這樣當 timer 到期時,系統會向由 sigev_notify_thread_id 指定的執行緒傳送訊號,否則可能程序中的任意執行緒都可能收到該訊號。這個選項是 linux 對 posix 標準的擴充套件,目前主要是 glibc 在實現 sigev_thread 的時候使用到,應用程式很少會需要用到這種模式。
linux核心定時器
度量時間差 時鐘中斷由系統的定時硬體以週期性的時間間隔產生,這個間隔 頻率 由核心根據hz來確定,hz是乙個與體系結構無關的常數,可配置 50 1200 在x86平台,預設值為1000.每秒鐘產生1000次時鐘中斷 每當時鐘中斷發生時,全域性變數jiffies就加1,因此其記錄了自linux啟動後時...
Linux 核心定時器
include include include include struct timer list my timer void func unsigned long data printk time out n data ld,pid ld n data,current pid mod timer ...
linux 定時器程式設計
在編寫應用程式的時候,經常需要用到定時器。根據使用情況,定時器的基本行為分為2種 single shot timer和repeating timer single shot timer 從註冊到終止只執行一次。repeating timer每次終止後自動執行。linux 在定時程式設計有以下幾種介面...