利用檔案描述符進行通知的定時器 timerfd

2021-08-03 15:57:48 字數 2934 閱讀 5434

timerfd api 是linux系統特有的,linux是在核心版本2.6.25中提供的。它可以從檔案描述符中讀取所建立定時器的到期通知。因為可以使用select()、poll()和epoll()將這種檔案描述符同其他描述符一同進行監控。

這組api中的3個系統呼叫,其操作與timer_create()、timer_settime()和timer_gettime()相類似。

新加入的第1個系統呼叫時timerfd_create(),它會建立乙個新的定時器物件,並返回乙個指代該物件的檔案描述符。

#include int timerfd_create(int clockid, int flags);

返回:若成功返回對應的描述符,若失敗返回-1

引數clockid的值可以設定為clock_realtime或clock_monotonic。參考下表。

時鐘型別

時 鐘 i d

描  述

clock_realtime

可設定的系統級實時時鐘

clock_monotonic

不可設定的恆定態時鐘

timerfd_create()最初實現將引數flags預留供未來使用,必須設定為0.不過,linux核心從2.6.27開始支援下面兩種flags標誌。

timerfd_create()建立的定時器使用完畢後,應呼叫close()關閉相應的檔案描述符,以便核心能夠釋放與定時器相關的資源。

系統呼叫timerfd_settime()可以配備(啟動)或解除(停止)由檔案描述符fd所指代的定時器。

#include int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspc *old_value);

返回:若成功返回0,若失敗返回-1

引數new_value為定時器指定新設定。引數old_value可以用來返回定時器的前一設定。如果不關心定時器的前一設定,可將old_value置為null。兩個引數均指向itimerspec結構。

引數flags可以是0,此時將new_value.it_value的值視為相對於呼叫timerfd_settime()時間點的相對時間,也可以設為tfd_timer_abstime,將其視為乙個絕對時間。

系統呼叫timerfd_gettime()返回檔案描述符fd所標識定時器的間隔及剩餘時間。

其中,itimerspec結構如下所示:

struct itimerspec

;struct timerspec

;

it_value指定了定時器首次到期的時間。如果it_interval的任一子字段非0,那麼就是乙個週期性定時器。在經歷了由it_value指定的 初次到期後,會按這些子欄位指定的頻率週期性到期。

#include int timerfd_gettime(int fd, struct itimerspec *curr_value);

返回:若成功返回0,若失敗返回-1

間隔以及距離下次到期的時間均返回curr_value指向的結構itimerspec中。即使是以tfd_timer_abstime標誌建立的絕對時間定時器,curr_value.it_vale欄位中返回值的意義也會保持不變。如果返回的結構curr_value.it_value中所有字段值均為0,那麼該定時器已經被解除。如果返回的結構curr_value.it_interval中的兩字段值均為0,那麼定時器只會到期一次,到期時間在curr_value.it_value中給出。

注意:呼叫fork()期間,子程序會繼承timerfd_create()所建立檔案描述符的拷貝。

一旦timerfd_settime()啟動了定時器,就可以從相應檔案描述符中呼叫read()來讀取定時器的到期資訊,出於這一目的,傳給read()的緩衝區必須足以容納乙個無符號8位元組整型(uint64_t)數。

在上次使用timerfd_settime()修改設定之後,或是最後一次執行read()後,如果發生了一起到多起定時器到期事件,那麼read()會立即返回,且返回的緩衝區中包含了已傳送的到期次數。如果並無定時器到期,read()會一直阻塞直至產生下乙個到期。也可以執行fcntl()的f_setfl操作為檔案描述符設定o_nonblock標誌,這時的讀動作的非阻塞的,且如果沒有定時器到期,則返回錯誤,並將errno值置為eagain。

如前所述,可以利用select()、pool()和epoll()對timerfd檔案描述符進行監控。如果定時器到期,會將對應的檔案描述符標記為可讀。

下面給乙個定時5s的例子,來看看這些api的使用:

#include #include #include #include #include #ifndef inftim

#define inftim -1

#endif //#ifndef inftim

int main(void)

struct itimerspec new_value;

new_value.it_interval.tv_sec = 5;

new_value.it_interval.tv_nsec = 0;

new_value.it_value.tv_sec = 5;

new_value.it_value.tv_nsec = 0;

if (timerfd_settime(ifd, 0, &new_value, null) != 0)

struct pollfd fdpoll;

fdpoll.fd = ifd;

fdpoll.events = pollin;

while (1)

if (fdpoll.revents & pollin)

printf("now, timer 5s\n");

} }close(ifd);

return 0;

}

描述符相關的時間定時器

描述符相關的定時器是指可以通過描述符進行操作的一種定時器。下面根據man pages提供的例子學習該定時器的具體應用。主要標頭檔案和函式有 include int timerfd create int clockid,int flags clockid 可為clock monotonic 或者 cl...

檔案描述符的複製

include int dup int fd int dup2 int fd,int fd2 這兩個函式可用來複製現有的檔案描述符。成功返回檔案描述符,出錯返回 1 dup返回當前可用檔案描述符中的最小數值。dup2中,fd2指定新的檔案描述符,如果fd2已經開啟,先將其關閉 如果fd等於fd2,返...

檔案描述符的理解

核心 kernel 利用檔案描述符 file descriptor 來訪問檔案。檔案描述符是非負整數。開啟現存盤案或新建檔案時,核心會返回乙個檔案描述符。讀寫檔案也需要使用檔案描述符來指定待讀寫的檔案。1.程序級的檔案描述符表 2.系統級的開啟檔案描述符表 3.檔案系統的i node表。檔案描述符是...