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.mzph.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_…