linux新增特性timerfd

2021-07-07 02:41:02 字數 3772 閱讀 2632

linux2.6.25版本新增了timerfd這個供使用者程式使用的定時介面,這個介面基於檔案描述符,當超時事件發生時,該檔案描述符就變為可讀。我首次接觸這個新特性是在muduo網路庫的定時器裡看到的,那麼新增乙個這樣的定時器介面有什麼意義呢?

要說明這個問題我得先給大家列舉一下linux下能實現定時功能的各個介面,然後通過逐一比較來說明原因

linux下的定時介面主要有如下幾種

.sleep()

.alarm()

.usleep()

.nanosleep()

.clock_nanosleep()

.getitimer()/setitimer()

.timer_create()/timer_settime/timer_gettime()/timer_delete()

.timerfd_create()/timerfd_gettime()/timer_settime()

以上便是linux下常用的一些定時介面

1.前三種sleep()/alarm()/usleep()在實現時可能用了sigalrm訊號,在多執行緒中使用訊號是相當麻煩的

2.nanosleep()/clock_nanosleep()會讓執行緒掛起,這樣會使程式失去響應,多執行緒網路程式設計中我們應該避免這樣做

3.getitimer()/timer_cteate()也是用訊號來deliver超時

而我們的timerfd_create()把時間變成了乙個檔案描述符,該檔案描述符會在超時時變得可讀,這種特性可以使我們在寫伺服器程式時,很方便的便把定時事件變成和其他i/o事件一樣的處理方式,並且此定時介面的精度也足夠的高,所以我們只要以後在寫i/o框架時用到了定時器就該首選timerfd_create()

(1)timerfd的建立

int timer_create(int clockid,int flags);

//成功返回0

第乙個引數一般為clock_realtime或者clock_monotonic,其引數意義為引數意義

clock_realtime:相對時間,從1970.1.1到目前時間,之所以說其為相對時間,是因為我們只要改變當前系統的時間,從1970.1.1到當前時間就會發生變化,所以說其為相對時間

clock_monotonic:與clock_realtime相反,它是以絕對時間為準,獲取的時間為系統最近一次重啟到現在的時間,更該系統時間對其沒影響

第二個引數為控制標誌:tfd_nonblock(非阻塞),tfd_cloexec(同o_cloexec)

(2)定時器的設定

int timerfd_settime(int fd,int flags

const

struct itimerspec *new_value

struct itimerspec *old_value);

//成功返回0

該函式的功能為啟動和停止定時器,第乙個引數fd為上面的timerfd_create()函式返回的定時器檔案描述符,第二個引數flags為0表示相對定時器,為tfd_timer_abstime表示絕對定時器,第三個引數new_value用來設定超時時間,為0表示停止定時器,第四個引數為原來的超時時間,一般設為null

需要注意的是我們可以通過clock_gettime獲取當前時間,如果是絕對定時器,那麼我們得獲取1970.1.1到當前時間(clock_realtime),在加上我們自己定的定時時間。若是相對定時,則要獲取我們系統本次開機到目前的時間加我們要定的時常(即獲取clock_monotonic時間)

上述引數中itimerspec的結構定義如下

struct itimerspec ;
其中it_value儲存首次超時時間值,即在哪個時間點超時的那個時間的值,it_interval為後續週期性超時的時間間隔,注意是時間間隔不是時間值啦

timespec的結構定義如下

struct timespec ;
需要注意的是當設定定時器後,我們就可以用read讀取定時器的檔案描述符了,當其可讀時,就是超時發生的時間,下面的例項中給出用法,請讀者仔細體會

以絕對超時為例

#include 

#include

#include

#include

#include

#include /* definition of uint64_t */

#define handle_error(msg) \

do while (0)

//列印當前定時距首次開始計時的時間

static

void print_elapsed_time(void)

if (clock_gettime(clock_monotonic, &curr) == -1)

handle_error("clock_gettime");

//時間差等於每次的當前時間減去start的開始時間

secs = curr.tv_sec - start.tv_sec;

nsecs = curr.tv_nsec - start.tv_nsec;

if (nsecs < 0)

printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);

}int main(int argc, char *argv)

if (clock_gettime(clock_realtime, &now) == -1)

handle_error("clock_gettime");

/* create a clock_realtime absolute timer with initial

expiration and interval as specified in command line */

new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);

new_value.it_value.tv_nsec = now.tv_nsec;

if (argc == 2) else

new_value.it_interval.tv_nsec = 0;

//生成與定時器關聯的檔案描述符

fd = timerfd_create(clock_realtime, 0);

if (fd == -1)

handle_error("timerfd_create");

if (timerfd_settime(fd, tfd_timer_abstime, &new_value, null) == -1)

handle_error("timerfd_settime");

//獲取並列印首次首次定時開始的時間

print_elapsed_time();

printf("timer started\n");

for (tot_exp = 0; tot_exp < max_exp;)

exit(exit_success);

}

編譯並執行上述程式,結果如下

當定一次值,設為3秒後超時

當定5次時,初次為3s後之後每1秒超時一次,執行結果如下

linux新增特性eventfd

首先說明的一點是eventfd是用來實現多程序或多執行緒的之間的事件通知的,那麼我們在沒接觸eventfd之前用到的事件通知機制都有那些?1.條件變數 2.管道 我們來逐一比較此倆中機制與eventfd的效果方面的好壞,首先,條件變數必須和互斥鎖結合使用,使用起來麻煩,而且效能未必比eventfd好...

Linux 2 6 35 新增特性 RPS RFS

本帖最後由 lenky0401 於 2010 08 15 23 02 編輯 懶得拷貝了 主要是試了拷貝,竟然拷貝不了,突然感覺還是qq空間發表日誌時的貼上功能強大,連文字帶圖一起拷貝過去了,之後還提示是否要把給抓取過來存到qq相簿 原文 linux 2.6.35於2010年8月1號發布,新增特性比較...

C 新增特性

引用申明 資料型別 引用名 變數名 1 在進行實參和形參的結合時,不會為形參分配記憶體空間,而是將形參作為實參的乙個別名,即在記憶體中沒有產生實參的副本,而使用一般變數傳遞函式引數時,發生函式呼叫時,是需要給形參分配儲存單元的。2 用引用能達到用指標傳遞的一樣效果,形參改變會影響實參。在主調函式的呼...