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 }
timerfd与epoll相关推荐
- 深入理解 Linux 的 epoll 机制
坚持思考,就会很酷 在 Linux 系统之中有一个核心武器:epoll 池,在高并发的,高吞吐的 IO 系统中常常见到 epoll 的身影. IO 多路复用 在 Go 里最核心的是 Goroutine ...
- linux timerfd系列函数总结:timerfd.h
Table of Contents 一.timerfd系列函数 (1)timerfd_create()函数 (2)timerfd_settime()函数 (3)timerfd_gettime()函数 ...
- SurfaceFlinger模块-VSYNC研究
Vsync信号是SurfaceFlinger进程中核心的一块逻辑,我们主要从以下几个方面着手讲解. 软件Vsync是怎么实现的,它是如何保持有效性的? systrace中看到的VSYNC信号如何解读, ...
- Linux下 timerfd创建定时器并使用 epoll 监听
介绍:Linux系统提供了timerfd系列的定时函数,其具体函数名如下 #include <sys/timerfd.h>int timerfd_create(int clockid, i ...
- eventfd和timerfd
在学习muduo中有看到eventfd和timerfd这2个函数,它们都可以通过文件描述符操作,能够很好的与epoll结合. eventfd用来在进程或线程之间通信,接口如下: ...
- Linux环境编程 用户层定时器使用一 timerfd的使用
timerfd是linux提供的定时器机制,基于文件描述符,定时器精度最高可达纳秒级别,接口包括定时器创建.启动定时器.关闭定时器和删除定时器.下面介绍一下timerfd API接口和一个结合epo ...
- timerfd API使用总结
timerfd 介绍 timerfd 是在Linux内核2.6.25版本中添加的接口,其是Linux为用户提供的一个定时器接口.这个接口基于文件描述符,所以可以被用于select/poll/epoll ...
- linux新的API signalfd、timerfd、eventfd使用说明
三种新的fd加入linux内核的的版本: signalfd:2.6.22 timerfd:2.6.25 eventfd:2.6.22 三种fd的意义: signalfd:传统的处理信号的方式是注册信号 ...
- Linux环境SOCKET编程5:定时器接口timerfd
1.概述 timerfd是Linux为用户程序提供的一个定时器接口.这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景.timerfd是lin ...
最新文章
- python定制框架知识点_我的第一个python web开发框架(25)——定制ORM(一)
- IBM copy service--flashcopy 实验
- ubuntu 16.10安装mysql_在Ubuntu 16.10安装mysql workbench报未安装软件包 libpng12-0错误的解决方法...
- mac mysql
- JAVA复习(对象的克隆、正则表达式)
- 工作107:插入请求头
- Android 获取天气数据
- 【福利】爱德华·阿什福德·李:人类与AI技术将是共生关系
- httpcline转发_go http请求转发
- 太原警方通过微博提醒您手机丢失如何保微信安全
- 单元测试中简单使用Mockito解决Spring Bean依赖树问题
- JavaScript中对于函数的形参实参个数匹配是如何做的?
- QT 实现采集即时音频信号并发送至另一台电脑播放
- 一个简单的互斥量与条件变量例子
- 十六进制转十进制_跟运维组学Python之秒懂十六进制
- oracle优化器analyzed,Oracle Optimizer:迁移到使用基于成本的优化器—–系列1.2-数据库专栏,ORACLE...
- 【笨嘴拙舌WINDOWS】Dj,oh!nonono,It is about DC
- 3.Go语言中常量,变量, 及其命名规则以及代码风格
- [SilkyBible] XviD系列-9
- el-input输入字母转化大写字母
热门文章
- file_get_content和curl的性能比较
- UVa 11468 (AC自动机 概率DP) Substring
- 替换Quartus 自带编辑器 (转COM张)
- hujingwei oracle_Oracle收缩表空间
- oracle安装出现getproces,oracle安装问题
- unity 删除服务器项目,在吗?有个支持批量构建项目的好东西推荐给你
- php判断记录,PHP判断数据库中的记录是否存在的方法,php数据库_PHP教程
- 物资管理系统c语言课程设计,C语言实现仓库物资管理系统
- python3怎么创建文件_Python3.5 创建文件的简单实例
- Win32ASM学习[10]:传送指令