timerfd與epoll

linux timerfd系列函數總結

網上關于timerfd的文章很多,在這兒歸納總結一下方便以后使用,順便貼出一個timerfd配合epoll使用的簡單例子

一、timerfd系列函數

  timerfd是Linux為用戶程序提供的一個定時器接口。這個接口基于文件描述符,通過文件描述符的可讀事件進行超時通知,因此可以配合select/poll/epoll等使用。
下面對timerfd系列函數先做一個簡單的介紹:

(1)timerfd_create()函數

復制代碼

#include <sys/timerfd.h>int timerfd_create(int clockid, int flags);
/* 
timerfd_create()函數創建一個定時器對象,同時返回一個與之關聯的文件描述符。
clockid:clockid標識指定的時鐘計數器,可選值(CLOCK_REALTIME、CLOCK_MONOTONIC。。。)
CLOCK_REALTIME:系統實時時間,隨系統實時時間改變而改變,即從UTC1970-1-1 0:0:0開始計時,中間時刻如果系統時間被用戶改成其他,則對應的時間相應改變
CLOCK_MONOTONIC:從系統啟動這一刻起開始計時,不受系統時間被用戶改變的影響
flags:參數flags(TFD_NONBLOCK(非阻塞模式)/TFD_CLOEXEC(表示當程序執行exec函數時本fd將被系統自動關閉,表示不傳遞)
*/

復制代碼

(2)timerfd_settime()函數

復制代碼

 1 #include <sys/timerfd.h>2 3 struct timespec {4     time_t tv_sec;                /* Seconds */5     long   tv_nsec;               /* Nanoseconds */6 };7 8 struct itimerspec {9     struct timespec it_interval;  /* Interval for periodic timer (定時間隔周期)*/
10     struct timespec it_value;     /* Initial expiration (第一次超時時間)*/
11 };
12 int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
13 /*
14     timerfd_settime()此函數用于設置新的超時時間,并開始計時,能夠啟動和停止定時器;
15     fd: 參數fd是timerfd_create函數返回的文件句柄
16     flags:參數flags為1代表設置的是絕對時間(TFD_TIMER_ABSTIME 表示絕對定時器);為0代表相對時間。
17     new_value: 參數new_value指定定時器的超時時間以及超時間隔時間
18     old_value: 如果old_value不為NULL, old_vlaue返回之前定時器設置的超時時間,具體參考timerfd_gettime()函數
19     
20     ** it_interval不為0則表示是周期性定時器。
21        it_value和it_interval都為0表示停止定時器
22 */

復制代碼

(3)timerfd_gettime()函數

復制代碼

1 int timerfd_gettime(int fd, struct itimerspec *curr_value);
2 /*
3     timerfd_gettime()函數獲取距離下次超時剩余的時間
4     curr_value.it_value 字段表示距離下次超時的時間,如果改值為0,表示計時器已經解除
5     改字段表示的值永遠是一個相對值,無論TFD_TIMER_ABSTIME是否被設置
6     curr_value.it_interval 定時器間隔時間
7 */

復制代碼

1 uint64_t exp = 0;
2 read(fd, &exp, sizeof(uint64_t)); 
3 //可以用read函數讀取計時器的超時次數,改值是一個8字節無符號的長整型

(4)下面貼出一個timerfd配合epoll函數的簡單例子

復制代碼

  1 /********************************************************2 * Filename: timerfd.c3 * Author: zhangwj4 * Desprition: a sample program of timerfd5 * Date: 2017-04-176 * Warnning:7 ********************************************************/8 #include <stdio.h>9 #include <stdint.h>10 #include <string.h>11 #include <stdlib.h>12 #include <pthread.h>13 #include <errno.h>14 #include <sys/epoll.h>15 #include <sys/timerfd.h>16 17 #if 018 struct timespec {19     time_t tv_sec;                /* Seconds */20     long   tv_nsec;               /* Nanoseconds */21 };22 23 struct itimerspec {24     struct timespec it_interval;  /* Interval for periodic timer */25     struct timespec it_value;     /* Initial expiration */26 };27 #endif28 29 #define EPOLL_LISTEN_CNT        25630 #define EPOLL_LISTEN_TIMEOUT    50031 32 #define LOG_DEBUG_ON 133 34 #ifdef LOG_DEBUG_ON 35 #define LOG_DEBUG(fmt, args...) \36     do {  \37         printf("[DEBUG]:");\38         printf(fmt "\n", ##args); \39     } while(0);40 #define LOG_INFO(fmt, args...) \41     do { \42         printf("[INFO]:");\43         printf(fmt "\n", ##args); \44     } while(0);45 #define LOG_WARNING(fmt, args...) \46     do { \47         printf("[WARNING]:");\48         printf(fmt "\n", ##args); \49     } while(0);50 #else51 #define LOG_DEBUG(fmt, args...) 52 #define LOG_INFO(fmt, args...) 53 #define LOG_WARNING(fmt, args...) 54 #endif55 #define LOG_ERROR(fmt, args...) \56     do{ \57         printf("[ERROR]:");\58         printf(fmt "\n", ##args);\59     }while(0);60 61 #define handle_error(msg) \62         do { perror(msg); exit(EXIT_FAILURE); } while (0)63 64 static int g_epollfd = -1;65 static int g_timerfd = -1;66 uint64_t tot_exp = 0;67 68 static void help(void)69 {70     exit(0);71 }72 73 static void print_elapsed_time(void)74 {75     static struct timespec start;76     struct timespec curr;77     static int first_call = 1;78     int secs, nsecs;79     80     if (first_call) {81         first_call = 0;82         if (clock_gettime(CLOCK_MONOTONIC, &start) == -1) 83             handle_error("clock_gettime");84     }   85     86     if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1) 87         handle_error("clock_gettime");88     89     secs = curr.tv_sec - start.tv_sec;90     nsecs = curr.tv_nsec - start.tv_nsec;91     if (nsecs < 0) {92         secs--;93         nsecs += 1000000000;94     }   95     printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);96 }97 98 void timerfd_handler(int fd)99 {
100     uint64_t exp = 0;
101     
102     read(fd, &exp, sizeof(uint64_t)); 
103     tot_exp += exp;
104     print_elapsed_time();
105     printf("read: %llu, total: %llu\n", (unsigned long long)exp, (unsigned long long)tot_exp);
106 
107     return;
108 }
109 
110 void epoll_event_handle(void)
111 {
112     int i = 0;
113     int fd_cnt = 0;
114     int sfd;
115     struct epoll_event events[EPOLL_LISTEN_CNT];    
116 
117     memset(events, 0, sizeof(events));
118     while(1) 
119     {   
120         /* wait epoll event */
121         fd_cnt = epoll_wait(g_epollfd, events, EPOLL_LISTEN_CNT, EPOLL_LISTEN_TIMEOUT); 
122         for(i = 0; i < fd_cnt; i++) 
123         {   
124             sfd = events[i].data.fd;
125             if(events[i].events & EPOLLIN) 
126             {   
127                 if (sfd == g_timerfd) 
128                 {
129                     timerfd_handler(sfd); 
130                 }   
131             }   
132         } 
133     }   
134 }
135 
136 int epoll_add_fd(int fd)
137 {
138     int ret;
139     struct epoll_event event;
140 
141     memset(&event, 0, sizeof(event));
142     event.data.fd = fd;
143     event.events = EPOLLIN | EPOLLET;
144 
145     ret = epoll_ctl(g_epollfd, EPOLL_CTL_ADD, fd, &event);
146     if(ret < 0) {
147         LOG_ERROR("epoll_ctl Add fd:%d error, Error:[%d:%s]", fd, errno, strerror(errno));
148         return -1;
149     }
150 
151     LOG_DEBUG("epoll add fd:%d--->%d success", fd, g_epollfd);
152     return 0;    
153 }
154 
155 int epollfd_init()
156 {
157     int epfd;
158 
159     /* create epoll fd */
160     epfd = epoll_create(EPOLL_LISTEN_CNT); 
161     if (epfd < 0) {
162         LOG_ERROR("epoll_create error, Error:[%d:%s]", errno, strerror(errno));
163         return -1;
164     }
165     g_epollfd = epfd;
166     LOG_DEBUG("epoll fd:%d create success", epfd);
167 
168     return epfd;
169 }
170 
171 int timerfd_init()
172 {
173     int tmfd;
174     int ret;
175     struct itimerspec new_value;
176 
177     new_value.it_value.tv_sec = 2;
178     new_value.it_value.tv_nsec = 0;
179     new_value.it_interval.tv_sec = 1;
180     new_value.it_interval.tv_nsec = 0;
181     
182     tmfd = timerfd_create(CLOCK_MONOTONIC, 0);
183     if (tmfd < 0) {
184         LOG_ERROR("timerfd_create error, Error:[%d:%s]", errno, strerror(errno));
185         return -1;
186     }
187 
188     ret = timerfd_settime(tmfd, 0, &new_value, NULL);
189     if (ret < 0) {
190         LOG_ERROR("timerfd_settime error, Error:[%d:%s]", errno, strerror(errno));
191         close(tmfd);
192         return -1;
193     }
194 
195     if (epoll_add_fd(tmfd)) {
196         close(tmfd);
197         return -1;
198     }
199     g_timerfd = tmfd;
200 
201     return 0;
202 }
203 
204 int main(int argc, char **argv)
205 {
206     if (epollfd_init() < 0) {
207         return -1;
208     }
209 
210     if (timerfd_init()) {
211         return -1;
212     }
213 
214     /* event handle */
215     epoll_event_handle();
216 
217     return 0;
218 }

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

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

相關文章

文件操作(解密加密)

文件加密&#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…

文件操作函數

fopen()函數參數&#xff1a; r 只讀的方式打開文件。 打開成功返回文件指針&#xff0c; 打開失敗返回NULL r 以讀寫方式打開文件。 文件必須存在 rb 以二進制模式讀寫文件&#xff0c;文件必須存在 rw 讀寫一個二進制文件&#xff0c;允許讀和寫 w 打開只寫文件&…

讀過的最好的epoll講解

首先我們來定義流的概念&#xff0c;一個流可以是文件&#xff0c;socket&#xff0c;pipe等等可以進行I/O操作的內核對象。 不管是文件&#xff0c;還是套接字&#xff0c;還是管道&#xff0c;我們都可以把他們看作流。 之后我們來討論I/O的操作&#xff0c;通過read&#xf…

文件操作函數(讀寫)

文件文本排序&#xff1a; 數組冒泡&#xff1a; #include<stdio.h>void swap(int *a,int *b) {int temp *a;*a *b;*b temp; }void bubble(int *p,int n) {int i;int j;for(i 0; i < n; i){for(j 1; j < n - i; j){if(p[j - 1] > p[j]){swap(&p[j-1],&…

文件操作(升級)

計算字符串“25 32 ” #include<stdio.h> #include<string.h>int calc_string(char *s) {char buf1[100] {0};char oper 0;char buf2[100] {0};int len strlen(s);int i;for(i 0; i < len; i){if( s[i] || - s[i] || * s[i] || / s[i] ){strncpy…

C語言指針轉換為intptr_t類型

C語言指針轉換為intptr_t類型 1、前言 今天在看代碼時&#xff0c;發現將之一個指針賦值給一個intptr_t類型的變量。由于之前沒有見過intptr_t這樣數據類型&#xff0c;憑感覺認為intptr_t是int類型的指針。感覺很奇怪&#xff0c;為何要將一個指針這樣做呢&#xff1f;如是果…

nginx epoll詳解

nginx epoll 事件模型 nginx做為一個異步高效的事件驅動型web服務器&#xff0c;在linux平臺中當系統支持epoll時nginx默認采用epoll來高效的處理事件。nginx中使用ngx_event_t結構來表示一個事件&#xff0c;先介紹下ngx_event_t結構體中成員的含義&#xff1a; struct ngx_ev…

Inotify機制

描述 Inotify API用于檢測文件系統變化的機制。Inotify可用于檢測單個文件&#xff0c;也可以檢測整個目錄。當檢測的對象是一個目錄的時候&#xff0c;目錄本身和目錄里的內容都會成為檢測的對象。 此種機制的出現的目的是當內核空間發生某種事件之后&#xff0c;可以立即通…

文件操作(二進制文件加密解密)

加密 #include<stdio.h> #include<string.h>void code(char *p,size_t n) {size_t i;for(i 0; i < n; i){p[i] 3;} }int main() {FILE *p1 fopen("./a.txt","r");FILE *p2 fopen("./b.txt","w");char buf[1024] {…

北京加密機現場select問題

問題描述 北京項目通過調用我們提供的庫libsigxt.a與加密機通信&#xff0c;c/s架構&#xff0c;客戶端啟用多個線程&#xff0c;每個線程流程有以下三步&#xff0c;連接加密機&#xff0c;簽名&#xff0c;關閉鏈接。在正常運行一段時間后會出現不能連接加密機服務問題。 連…

拼接字符串(帶參程序)

1.用strcat拼接函數可以實現 #include<stdio.h> #include<string.h>int main(int argc,char ** argv) {char str[100] {0};int i;for( i 1; i < argc; i){strcat(str,argv[i]);}printf("str %s\n",str);return 0; } 2.用sprintf函數也可以實現 #in…

詳細解釋signal和sigaction以及SIG_BLOCK

signal&#xff0c;此函數相對簡單一些&#xff0c;給定一個信號&#xff0c;給出信號處理函數則可&#xff0c;當然&#xff0c;函數簡單&#xff0c;其功能也相對簡單許多&#xff0c;簡單給出個函數例子如下&#xff1a; [cpp] view plain copy 1 #include <signal.h>…

處理SIGCHLD信號

在上一講中&#xff0c;我們使用fork函數得到了一個簡單的并發服務器。然而&#xff0c;這樣的程序有一個問題&#xff0c;就是當子進程終止時&#xff0c;會向父進程發送一個SIGCHLD信號&#xff0c;父進程默認忽略&#xff0c;導致子進程變成一個僵尸進程。僵尸進程一定要處理…

文件操作(stat)

/*** stat.c ***/ #include<stdio.h> #include<string.h> #include<sys/stat.h> #include<stdlib.h>int main() {struct stat st {0}; //定義一個結構體&#xff0c;名字叫ststat("./a.txt",&st); //調用完stat函數之后&…

nginx源碼閱讀(一).綜述

前言 nginx作為一款開源的輕量級高性能web服務器,是非常值得立志從事服務端開發方向的人學習的。現今nginx的最新版本是nginx-1.13.6,代碼量也日漸龐大,但是由于其核心思想并沒改變,為了降低閱讀難度,我選擇的是nginx-1.0.15版本,并且由于時間和水平有限,重點關注的是nginx的啟…

文件操作(stat函數)

stat函數可以獲取文件信息 /*** stat.c ***/ #include<stdio.h> #include<string.h> #include<sys/stat.h> #include<stdlib.h>int main() {struct stat st {0}; //定義一個結構體&#xff0c;名字叫ststat("./a.txt",&st); …

文件操作(結構體)

將結構體內容寫入到文件中 #include<stdio.h> #include<string.h>struct student {char name[100];int age; };int main() {struct student st {"wangqinghe",30};FILE * p fopen("./c.txt","wb");fwrite(&st,sizeof(st),1,p…

nginx源碼閱讀(二).初始化:main函數及ngx_init_cycle函數

前言 在分析源碼時,我們可以先把握主干,然后其他部分再挨個分析就行了。接下來我們先看看nginx的main函數干了些什么。 main函數 這里先介紹一些下面會遇到的變量類型: ngx_int_t: typedef intptr_t ngx_int_t; 64位機器上,intptr_t為long int, 即typedef long int intptr_…