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,一经查实,立即删除!

相关文章

linux僵尸进程产生的原因以及如何避免产生僵尸进程defunct

给进程设置僵尸状态的目的是维护子进程的信息&#xff0c;以便父进程在以后某个时间获取。这些信息包括子进程的进程ID、终止状态以及资源利用信息(CPU时间&#xff0c;内存使用量等等)。如果一个进程终止&#xff0c;而该进程有子进程处于僵尸状态&#xff0c;那么它的所有僵尸…

linux下僵尸进程(Defunct进程)的产生与避免

在测试基于 DirectFBGstreamer 的视频联播系统的一个 Demo 的时候&#xff0c;其中大量使用 system 调用的语句&#xff0c;例如在 menu 代码中的 system("./play") &#xff0c;而且多次执行&#xff0c;这种情况下&#xff0c;在 ps -ef 列表中出现了大量的 defunc…

读过的最好的epoll讲解

首先我们来定义流的概念&#xff0c;一个流可以是文件&#xff0c;socket&#xff0c;pipe等等可以进行I/O操作的内核对象。 不管是文件&#xff0c;还是套接字&#xff0c;还是管道&#xff0c;我们都可以把他们看作流。 之后我们来讨论I/O的操作&#xff0c;通过read&#xf…

C语言指针转换为intptr_t类型

C语言指针转换为intptr_t类型 1、前言 今天在看代码时&#xff0c;发现将之一个指针赋值给一个intptr_t类型的变量。由于之前没有见过intptr_t这样数据类型&#xff0c;凭感觉认为intptr_t是int类型的指针。感觉很奇怪&#xff0c;为何要将一个指针这样做呢&#xff1f;如是果…

北京加密机现场select问题

问题描述 北京项目通过调用我们提供的库libsigxt.a与加密机通信&#xff0c;c/s架构&#xff0c;客户端启用多个线程&#xff0c;每个线程流程有以下三步&#xff0c;连接加密机&#xff0c;签名&#xff0c;关闭链接。在正常运行一段时间后会出现不能连接加密机服务问题。 连…

处理SIGCHLD信号

在上一讲中&#xff0c;我们使用fork函数得到了一个简单的并发服务器。然而&#xff0c;这样的程序有一个问题&#xff0c;就是当子进程终止时&#xff0c;会向父进程发送一个SIGCHLD信号&#xff0c;父进程默认忽略&#xff0c;导致子进程变成一个僵尸进程。僵尸进程一定要处理…

nginx源码阅读(一).综述

前言 nginx作为一款开源的轻量级高性能web服务器,是非常值得立志从事服务端开发方向的人学习的。现今nginx的最新版本是nginx-1.13.6,代码量也日渐庞大,但是由于其核心思想并没改变,为了降低阅读难度,我选择的是nginx-1.0.15版本,并且由于时间和水平有限,重点关注的是nginx的启…

系统级性能分析工具perf的介绍与使用

系统级性能优化通常包括两个阶段&#xff1a;性能剖析&#xff08;performance profiling&#xff09;和代码优化。 性能剖析的目标是寻找性能瓶颈&#xff0c;查找引发性能问题的原因及热点代码。 代码优化的目标是针对具体性能问题而优化代码或编译选项&#xff0c;以改善软…

C/C++内存问题检查利器——Purify

C&#xff0f;C内存问题检查利器——Purify 一、 引言 我们都知道软件的测试&#xff08;在以产品为主的软件公司中叫做QA—Quality Assessment&#xff09;占了整个软件工程的30% -50%&#xff0c;但有这么一种说法&#xff0c;即使是最优秀测试专家设计出来的测试…

浅析三种特殊进程:孤儿进程,僵尸进程和守护进程

其实有时想想linux内核的设计也蕴含着很多人生哲学,在linux中有这么几个特殊进程中,我们一开始见到它们的名字可能还会觉得很诧异,但在了解完了原理后,我们仔细想想,这样的命名也不无道理!下面我就给大家分别介绍一下这三种特殊的进程! 1.孤儿进程 如果父进程先退出,子进程还没…

差生文具多之(二): perf

栈回溯和符号解析是使用 perf 的两大阻力&#xff0c;本文以应用程序 fio 的观测为例子&#xff0c;提供一些处理它们的经验法则&#xff0c;希望帮助大家无痛使用 perf。 前言 系统级性能优化通常包括两个阶段&#xff1a;性能剖析和代码优化&#xff1a; 性能剖析的目标是寻…

Linux下的I/O复用与epoll详解(ET与LT)

前言 I/O多路复用有很多种实现。在linux上&#xff0c;2.4内核前主要是select和poll&#xff0c;自Linux 2.6内核正式引入epoll以来&#xff0c;epoll已经成为了目前实现高性能网络服务器的必备技术。尽管他们的使用方法不尽相同&#xff0c;但是本质上却没有什么区别。本文将重…

彻底学会使用epoll(一)——ET模式实现分析

注&#xff1a;之前写过两篇关于epoll实现的文章&#xff0c;但是感觉懂得了实现原理并不一定会使用&#xff0c;所以又决定写这一系列文章&#xff0c;希望能够对epoll有比较清楚的认识。是请大家转载务必注明出处&#xff0c;算是对我劳动成果的一点点尊重吧。另外&#xff0…

sys/queue.h分析(图片复制不过来,查看原文)

这两天有兴趣学习使用了下系统头文件sys/queue.h中的链表/队列的实现&#xff0c;感觉实现的很是优美&#xff0c;关键是以后再也不需要自己实现这些基本的数据结构了&#xff0c;哈哈&#xff01; 我的系统环境是 正好需要使用队列&#xff0c;那么本篇就以其中的尾队列&…

线程池原理及C语言实现线程池

备注&#xff1a;该线程池源码参考自传直播客培训视频配套资料&#xff1b; 源码&#xff1a;https://pan.baidu.com/s/1zWuoE3q0KT5TUjmPKTb1lw 密码&#xff1a;pp42 引言&#xff1a;线程池是一种多线程处理形式&#xff0c;大多用于高并发服务器上&#xff0c;它能合理有效…

iptables 的mangle表

mangle表的主要功能是根据规则修改数据包的一些标志位&#xff0c;以便其他规则或程序可以利用这种标志对数据包进行过滤或策略路由。 内网的客户机通过Linux主机连入Internet&#xff0c;而Linux主机与Internet连接时有两条线路&#xff0c;它们的网关如图所示。现要求对内网进…

Linux之静态库

命名规则&#xff1a; lib 库的名字 .a 制作步骤 生成对应.o文件 .c .o 将生成的.o文件打包 ar rcs 静态库的名字&#xff08;libMytest.a&#xff09; 生成的所有的.o 发布和使用静态库&#xff1a; 1&#xff09; 发布静态 2&#xff09; 头文件 文件如下图所示&…

Linux之动态库

命令规则 lib 名字 .so 制作步骤 1&#xff09;生成与位置无关的代码&#xff08;生成与位置无关的代码&#xff09; 2&#xff09;将.o打包成共享库&#xff08;动态库&#xff09; 发布和使用共享库 动态库运行原理&#xff1a; 生成动态库&#xff1a; gcc -fPIC -c *.c -…

linux下源码安装vsftpd-3.0.2

1&#xff09;在http://vsftpd.beasts.org/网站中查找并下载 vsftpd-3.0.2.tar.gz源码包 2)如果自己的机器上安装有yum可以用yum grouplist | less指令查看以下开发环境&#xff0c;当然这一步不做也行 3&#xff09;拆解源码包 4&#xff09;查看源码包 5&#xff09;编辑…

Gdb 调试core文件详解

一&#xff0c;什么是coredump 我们经常听到大家说到程序core掉了&#xff0c;需要定位解决&#xff0c;这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止&#xff0c;并且在满足一定条件下&#xff08;这里为什么说需要满足一定的条件呢&#…