timerfd API使用總結

timerfd 介紹

timerfd 是在Linux內核2.6.25版本中添加的接口,其是Linux為用戶提供的一個定時器接口。這個接口基于文件描述符,所以可以被用于select/poll/epoll的場景。當使用timerfd API創建多個定時器任務并置于poll中進行事件監聽,當沒有可響應的事件,則程序阻塞在poll中,當有事件發生,通過poll的這個事件入口,對產生的事件進行響應,從而構成了一個事件輪訓程序。

timerfd 相關函數

#include <time.h>
int clock_gettime(clockid_t clockid, struct timespec *tp);
  • 1
  • 2
  • 3

clock_gettime函數主要用于獲取系統時間,精確到納秒級別。在編譯時需要添加-lrt庫,clockid_t clockid指定用何種模式獲取時間,struct timespec *tp用于存儲獲取到的時間。其中clockid主要有如下常用的參數:?
CLOCK_REALTIME:系統實時時間,隨系統實時時間改變而改變,即從UTC1970-1-1 0:0:0開始計時,中間時刻如果系統時間被用戶改成其他,則對應的時間相應改變?
CLOCK_MONOTONIC:從系統啟動這一刻起開始計時,不受系統時間被用戶改變的影響?
  CLOCK_PROCESS_CPUTIME_ID:本進程到當前代碼系統CPU花費的時間?
  CLOCK_THREAD_CPUTIME_ID:本線程到當前代碼系統CPU花費的時間

#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);
int timerfd_settime(int fd, int flags, const struct itimerspec *new_value,struct itimerspec *old_value);
int timerfd_gettime(int fd, struct itimerspec *curr_value);
  • 1
  • 2
  • 3
  • 4
  • 5
  • timerfd_create函數主要用于生成一個定時器對象,返回與之關聯的文件描述符,clockid可以設置CLOCK_REALTIME和CLOCK_MONOTONIC,flags可以設置為TFD_NONBLOCK(非阻塞),TFD_CLOEXEC(同O_CLOEXEC)
  • timerfd_settime用于啟動和停止定時器,fd為timerfd_create獲得的定時器文件描述符,flags為0表示是相對定時器,為TFD_TIMER_ABSTIME表示是絕對定時器。const struct itimerspec *new_value表示設置超時的時間。?
    其數據結構:
  struct timespec {time_t tv_sec;                /* Seconds */long   tv_nsec;               /* Nanoseconds */};struct itimerspec {struct timespec it_interval;  /* Interval for periodic timer */struct timespec it_value;     /* Initial expiration */};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

需要注意的是itimerspec 結構成員表示的意義:?
it_value是首次超時時間,需要填寫從clock_gettime獲取的時間,并加上要超時的時間。 it_interval是后續周期性超時時間,是多少時間就填寫多少。?
it_interval不為0則表示是周期性定時器。?
it_value和it_interval都為0表示停止定時器。

  • timerfd_gettime此函數用于獲得定時器距離下次超時還剩下的時間。如果調用時定時器已經到期,并且該定時器處于循環模式(設置超時時間時struct itimerspec::it_interval不為0),那么調用此函數之后定時器重新開始計時。

參考示例

示例一


int tu_set_timer(tu_timer_t * timer, uint64_t milliseconds, bool continious, timer_handler_cb_t timer_handler_cb, void * timer_handler_arg)
{int fd;struct itimerspec its;//創建的定時器    fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);if (fd == -1){LOG_PRINT("Error creating timer");return -1;}//設置超時時間its.it_value.tv_sec = (milliseconds * 1000000) / 1000000000;its.it_value.tv_nsec = (milliseconds * 1000000) % 1000000000;//如果是周期定時器,則設置it_interval,如果不是則為0its.it_interval.tv_sec = continious ? its.it_value.tv_sec : 0;its.it_interval.tv_nsec = continious ? its.it_value.tv_nsec : 0;//設置定時到達后的響應函數及其函數參數timer->timer_handler_cb = timer_handler_cb;timer->timer_handler_arg = timer_handler_arg;timer->continious = continious;//標記是否為循環周期定時器//啟動定時器,并將文件描述符添加到poll中監聽if ((timerfd_settime(fd, 0, &its, NULL) == 0) && ((timer->fd_index = polling_define_poll_fd(fd, POLLIN, tu_timer_handler, timer)) != -1)){timer->in_use = true;return 0;}close(fd);return -1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

示例二


int tu_set_timer_realtime(tu_timer_t * timer, uint64_t milliseconds, bool continious, timer_handler_cb_t timer_handler_cb, void * timer_handler_arg)
{int fd;struct itimerspec its;struct timespec now;time_t tv_sec;long tv_nsec;//獲取絕對時間if(clock_gettime(CLOCK_REALTIME,&now) == -1){LOG_PRINT("Error clock_gettime timer\n");return -1;}//創建定時器,非阻塞方式   fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);if (fd == -1){LOG_PRINT("Error creating timer\n");return -1;}//計算時間tv_sec = (milliseconds * 1000000) / 1000000000;tv_nsec = (milliseconds * 1000000) % 1000000000;//設置到期時間its.it_value.tv_sec  = now.tv_sec + tv_sec;its.it_value.tv_nsec = now.tv_nsec + tv_nsec;//如果使用循環模式,設置循環間隔its.it_interval.tv_sec = continious ? tv_sec : 0;its.it_interval.tv_nsec = continious ? tv_nsec : 0;//設置定時到達后的響應函數及其函數參數timer->timer_handler_cb = timer_handler_cb;timer->timer_handler_arg = timer_handler_arg;timer->continious = continious;//啟動定時器,并將文件描述符添加到poll中監聽if ((timerfd_settime(fd,TFD_TIMER_ABSTIME, &its, NULL) == 0) && ((timer->fd_index = polling_define_poll_fd(fd, POLLIN, tu_timer_handler, timer)) != -1)){timer->in_use = true;LOG_PRINT("tu_set_timer_realtime--\n");return 0;}LOG_PRINT("Error setting timer\n");close(fd);return -1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

poll中的回調函數

void tu_timer_handler(void * arg)
{tu_timer_t * timer = arg;uint64_t exp;if (timer->continious)//重復定時器{if (read(polling_fds[timer->fd_index].fd, &exp, sizeof(uint64_t)) != sizeof(uint64_t)){LOG_PRINT("%p ERROR timer read. Killing timer.\n", timer);tu_kill_timer(timer);}}else{tu_kill_timer(timer);//關閉定時器}//調用定時器處理函數timer->timer_handler_cb(timer->timer_handler_arg);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384995.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384995.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384995.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

#if/#else/#endif

在linux環境下寫c代碼時會嘗試各種方法或調整路徑&#xff0c;需要用到#if #include<stdio.h>int main(){int i; #if 0i 1; #elsei 2; #endifprintf("i %d",i);return 0; } 有時候會調整代碼&#xff0c;但是又不是最終版本的更換某些值&#xff0c;就需要注…

內存分配調用

通過函數給實參分配內存&#xff0c;可以通過二級指針實現 #include<stdio.h> #incldue<stdlib.h>void getheap(int *p) //錯誤的模型 {p malloc(100); }void getheap(int **p) //正確的模型 {*p malloc(100); } int main() {int *p NULL;getheap(&p);free(p…

ESP傳輸模式拆解包流程

一、 ESP簡介ESP&#xff0c;封裝安全載荷協議(Encapsulating SecurityPayloads)&#xff0c;是一種Ipsec協議&#xff0c;用于對IP協議在傳輸過程中進行數據完整性度量、來源認證、加密以及防回放攻擊。可以單獨使用&#xff0c;也可以和AH一起使用。在ESP頭部之前的IPV4…

結構體成員內存對齊

#include<stdio.h> struct A {int A; };int main() {struct A a;printf("%d\n",sizeof(a));return 0; } 運行結果&#xff1a;4 #include<stdio.h> struct A {int a;int b&#xff1b; };int main() {struct A a;printf("%d\n",sizeof(a))…

C庫函數-fgets()

函數聲明&#xff1a;char *fgets(char *str,int n,FILE *stream) 函數介紹&#xff1a;從指定的stream流中讀取一行&#xff0c;并把它存儲在str所指向的字符串中。當讀取到&#xff08;n-1&#xff09;個字符時&#xff0c;獲取讀取到換行符時&#xff0c;或者到達文件末尾時…

linux內核netfilter模塊分析之:HOOKs點的注冊及調用

1: 為什么要寫這個東西?最近在找工作,之前netfilter 這一塊的代碼也認真地研究過&#xff0c;應該每個人都是這樣的你懂 不一定你能很準確的表達出來。 故一定要化些時間把這相關的東西總結一下。 0&#xff1a;相關文檔linux 下 nf_conntrack_tuple 跟蹤記錄 其中可以根據內…

指定結構體元素的位字段

struct B {char a:4; //a這個成員值占了4bitchar b:2;char c:2; } 占了1個字節 struct B {int a:4; //a這個成員值占了4bitchar b:2;char c:2; } 占了8個字節 控制LED燈的結構體&#xff1a; struct E {char a1:1;char a2:1;char a3:1;char a4:1;char a5:1;char a6:1;char a7:1…

網絡抓包工具 wireshark 入門教程

Wireshark&#xff08;前稱Ethereal&#xff09;是一個網絡數據包分析軟件。網絡數據包分析軟件的功能是截取網絡數據包&#xff0c;并盡可能顯示出最為詳細的網絡數據包數據。Wireshark使用WinPCAP作為接口&#xff0c;直接與網卡進行數據報文交換。網絡管理員使用Wireshark來…

結構體中指針

結構體中帶有指針的情況 #include<stdio.h>struct man {char *name;int age; };int main() {struct man m {"tom",20};printf("name %s, age %d\n",m.name,m.age);return 0; } 運行結果&#xff1a; exbotubuntu:~/wangqinghe/C/20190714$ gcc st…

python使用opencv提取視頻中的每一幀、最后一幀,并存儲成圖片

提取視頻每一幀存儲圖片 最近在搞視頻檢測問題&#xff0c;在用到將視頻分幀保存為圖片時&#xff0c;圖片可以保存&#xff0c;但是會出現(-215:Assertion failed) !_img.empty() in function cv::imwrite問題而不能正常運行&#xff0c;在檢查代碼、檢查路徑等措施均無果后&…

結構體參數

結構體作為函數參數&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h>struct student {char name[10];int age; };void print_student(struct student s) {printf("name %s,age %d\n",s.name,s.age); } void set_studen…

線程間通信之eventfd

線程間通信之eventfd man手冊中的解釋&#xff1a; eventfd()創建了一個“eventfd對象”&#xff0c; 通過它能夠實現用戶態程序間(我覺得這里主要指線程而非進程)的等待/通知機制&#xff0c;以及內核態向用戶態通知的機制&#xff08;未考證&#xff09;。 此對象包含了一個…

【linux 開發】定時器使用setitimer

setitimer Linux 為每一個進程提供了 3 個 setitimer 間隔計時器&#xff1a; ITIMER_REAL&#xff1a;減少實際時間&#xff0c;到期的時候發出 SIGALRM 信號。ITIMER_VIRTUAL&#xff1a;減少有效時間 (進程執行的時間)&#xff0c;產生 SIGVTALRM 信號。ITIMER_PROF&#…

文件操作(寫)

/*** file.c ***/ #include<stdio.h>int main() {//用寫的方式打開一個文件 //w的意思是文件如果不存在&#xff0c;就建立一個文件&#xff0c;如果文件存在就覆蓋FILE *p fopen("/home/exbot/wangqinghe/C/20190716/file1.txt","w");fputs(&qu…

定時器timerfd

1.為什么要加入此定時器接口 linux2.6.25版本新增了timerfd這個供用戶程序使用的定時接口&#xff0c;這個接口基于文件描述符&#xff0c;當超時事件發生時&#xff0c;該文件描述符就變為可讀。我首次接觸這個新特性是在muduo網絡庫的定時器里看到的&#xff0c;那么新增一個…

文件操作(讀)

讀一行&#xff1a; #include<stdio.h> #include<string.h> #include<stdlib.h> const int maxn 10; int main() {char s[1024] {0};FILE *p fopen("/home/exbot/wangqinghe/C/20190716/file.txt","r");//第一個參數是一個內存地址&…

timerfd與epoll

linux timerfd系列函數總結 網上關于timerfd的文章很多&#xff0c;在這兒歸納總結一下方便以后使用&#xff0c;順便貼出一個timerfd配合epoll使用的簡單例子 一、timerfd系列函數 timerfd是Linux為用戶程序提供的一個定時器接口。這個接口基于文件描述符&#xff0c;通過文…

文件操作(解密加密)

文件加密&#xff1a; #include<stdio.h> #include<string.h> #include<stdlib.h>void code(char *s) {while(*s){(*s);s;} }int main() {char s[1024] {0};FILE *p fopen("/home/exbot/wangqinghe/C/20190716/file.txt","r");FILE *p…

linux僵尸進程產生的原因以及如何避免產生僵尸進程defunct

給進程設置僵尸狀態的目的是維護子進程的信息&#xff0c;以便父進程在以后某個時間獲取。這些信息包括子進程的進程ID、終止狀態以及資源利用信息(CPU時間&#xff0c;內存使用量等等)。如果一個進程終止&#xff0c;而該進程有子進程處于僵尸狀態&#xff0c;那么它的所有僵尸…

linux下僵尸進程(Defunct進程)的產生與避免

在測試基于 DirectFBGstreamer 的視頻聯播系統的一個 Demo 的時候&#xff0c;其中大量使用 system 調用的語句&#xff0c;例如在 menu 代碼中的 system("./play") &#xff0c;而且多次執行&#xff0c;這種情況下&#xff0c;在 ps -ef 列表中出現了大量的 defunc…