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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

timerfd API使用总结

發(fā)布時(shí)間:2023/11/30 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 timerfd API使用总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

timerfd 介紹

timerfd 是在Linux內(nèi)核2.6.25版本中添加的接口,其是Linux為用戶提供的一個(gè)定時(shí)器接口。這個(gè)接口基于文件描述符,所以可以被用于select/poll/epoll的場景。當(dāng)使用timerfd API創(chuàng)建多個(gè)定時(shí)器任務(wù)并置于poll中進(jìn)行事件監(jiān)聽,當(dāng)沒有可響應(yīng)的事件,則程序阻塞在poll中,當(dāng)有事件發(fā)生,通過poll的這個(gè)事件入口,對產(chǎn)生的事件進(jìn)行響應(yīng),從而構(gòu)成了一個(gè)事件輪訓(xùn)程序。

timerfd 相關(guān)函數(shù)

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

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

#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函數(shù)主要用于生成一個(gè)定時(shí)器對象,返回與之關(guān)聯(lián)的文件描述符,clockid可以設(shè)置CLOCK_REALTIME和CLOCK_MONOTONIC,flags可以設(shè)置為TFD_NONBLOCK(非阻塞),TFD_CLOEXEC(同O_CLOEXEC)
  • timerfd_settime用于啟動(dòng)和停止定時(shí)器,fd為timerfd_create獲得的定時(shí)器文件描述符,flags為0表示是相對定時(shí)器,為TFD_TIMER_ABSTIME表示是絕對定時(shí)器。const struct itimerspec *new_value表示設(shè)置超時(shí)的時(shí)間。?
    其數(shù)據(jù)結(jié)構(gòu):
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 結(jié)構(gòu)成員表示的意義:?
it_value是首次超時(shí)時(shí)間,需要填寫從clock_gettime獲取的時(shí)間,并加上要超時(shí)的時(shí)間。 it_interval是后續(xù)周期性超時(shí)時(shí)間,是多少時(shí)間就填寫多少。?
it_interval不為0則表示是周期性定時(shí)器。?
it_value和it_interval都為0表示停止定時(shí)器。

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

參考示例

示例一

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;//創(chuàng)建的定時(shí)器 fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);if (fd == -1){LOG_PRINT("Error creating timer");return -1;}//設(shè)置超時(shí)時(shí)間its.it_value.tv_sec = (milliseconds * 1000000) / 1000000000;its.it_value.tv_nsec = (milliseconds * 1000000) % 1000000000;//如果是周期定時(shí)器,則設(shè)置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;//設(shè)置定時(shí)到達(dá)后的響應(yīng)函數(shù)及其函數(shù)參數(shù)timer->timer_handler_cb = timer_handler_cb;timer->timer_handler_arg = timer_handler_arg;timer->continious = continious;//標(biāo)記是否為循環(huán)周期定時(shí)器//啟動(dòng)定時(shí)器,并將文件描述符添加到poll中監(jiān)聽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;//獲取絕對時(shí)間if(clock_gettime(CLOCK_REALTIME,&now) == -1){LOG_PRINT("Error clock_gettime timer\n");return -1;}//創(chuàng)建定時(shí)器,非阻塞方式 fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);if (fd == -1){LOG_PRINT("Error creating timer\n");return -1;}//計(jì)算時(shí)間tv_sec = (milliseconds * 1000000) / 1000000000;tv_nsec = (milliseconds * 1000000) % 1000000000;//設(shè)置到期時(shí)間its.it_value.tv_sec = now.tv_sec + tv_sec;its.it_value.tv_nsec = now.tv_nsec + tv_nsec;//如果使用循環(huán)模式,設(shè)置循環(huán)間隔its.it_interval.tv_sec = continious ? tv_sec : 0;its.it_interval.tv_nsec = continious ? tv_nsec : 0;//設(shè)置定時(shí)到達(dá)后的響應(yīng)函數(shù)及其函數(shù)參數(shù)timer->timer_handler_cb = timer_handler_cb;timer->timer_handler_arg = timer_handler_arg;timer->continious = continious;//啟動(dòng)定時(shí)器,并將文件描述符添加到poll中監(jiān)聽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中的回調(diào)函數(shù)

void tu_timer_handler(void * arg) {tu_timer_t * timer = arg;uint64_t exp;if (timer->continious)//重復(fù)定時(shí)器{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);//關(guān)閉定時(shí)器}//調(diào)用定時(shí)器處理函數(shù)timer->timer_handler_cb(timer->timer_handler_arg); }

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。