日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

timerfd API使用总结

發布時間:2023/11/30 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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); }

總結

以上是生活随笔為你收集整理的timerfd API使用总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。