网上关于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()函数

 #include <sys/timerfd.h>

 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 (第一次超时时间)*/
};
int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
/*
timerfd_settime()此函数用于设置新的超时时间,并开始计时,能够启动和停止定时器;
fd: 参数fd是timerfd_create函数返回的文件句柄
flags:参数flags为1代表设置的是绝对时间(TFD_TIMER_ABSTIME 表示绝对定时器);为0代表相对时间。
new_value: 参数new_value指定定时器的超时时间以及超时间隔时间
old_value: 如果old_value不为NULL, old_vlaue返回之前定时器设置的超时时间,具体参考timerfd_gettime()函数 ** it_interval不为0则表示是周期性定时器。
it_value和it_interval都为0表示停止定时器
*/

(3)timerfd_gettime()函数

 int timerfd_gettime(int fd, struct itimerspec *curr_value);
/*
timerfd_gettime()函数获取距离下次超时剩余的时间
curr_value.it_value 字段表示距离下次超时的时间,如果改值为0,表示计时器已经解除
改字段表示的值永远是一个相对值,无论TFD_TIMER_ABSTIME是否被设置
curr_value.it_interval 定时器间隔时间
*/
 uint64_t exp = ;
read(fd, &exp, sizeof(uint64_t));
//可以用read函数读取计时器的超时次数,改值是一个8字节无符号的长整型

(4)下面贴出一个timerfd配合epoll函数的简单例子

 /********************************************************
* Filename: timerfd.c
* Author: zhangwj
* Desprition: a sample program of timerfd
* Date: 2017-04-17
* Warnning:
********************************************************/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <sys/epoll.h>
#include <sys/timerfd.h> #if 0
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 */
};
#endif #define EPOLL_LISTEN_CNT 256
#define EPOLL_LISTEN_TIMEOUT 500 #define LOG_DEBUG_ON 1 #ifdef LOG_DEBUG_ON
#define LOG_DEBUG(fmt, args...) \
do { \
printf("[DEBUG]:");\
printf(fmt "\n", ##args); \
} while();
#define LOG_INFO(fmt, args...) \
do { \
printf("[INFO]:");\
printf(fmt "\n", ##args); \
} while();
#define LOG_WARNING(fmt, args...) \
do { \
printf("[WARNING]:");\
printf(fmt "\n", ##args); \
} while();
#else
#define LOG_DEBUG(fmt, args...)
#define LOG_INFO(fmt, args...)
#define LOG_WARNING(fmt, args...)
#endif
#define LOG_ERROR(fmt, args...) \
do{ \
printf("[ERROR]:");\
printf(fmt "\n", ##args);\
}while(); #define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while () static int g_epollfd = -;
static int g_timerfd = -;
uint64_t tot_exp = ; static void help(void)
{
exit();
} static void print_elapsed_time(void)
{
static struct timespec start;
struct timespec curr;
static int first_call = ;
int secs, nsecs; if (first_call) {
first_call = ;
if (clock_gettime(CLOCK_MONOTONIC, &start) == -)
handle_error("clock_gettime");
} if (clock_gettime(CLOCK_MONOTONIC, &curr) == -)
handle_error("clock_gettime"); secs = curr.tv_sec - start.tv_sec;
nsecs = curr.tv_nsec - start.tv_nsec;
if (nsecs < ) {
secs--;
nsecs += ;
}
printf("%d.%03d: ", secs, (nsecs + ) / );
} void timerfd_handler(int fd)
{
uint64_t exp = ; read(fd, &exp, sizeof(uint64_t));
tot_exp += exp;
print_elapsed_time();
printf("read: %llu, total: %llu\n", (unsigned long long)exp, (unsigned long long)tot_exp); return;
} void epoll_event_handle(void)
{
int i = ;
int fd_cnt = ;
int sfd;
struct epoll_event events[EPOLL_LISTEN_CNT]; memset(events, , sizeof(events));
while()
{
/* wait epoll event */
fd_cnt = epoll_wait(g_epollfd, events, EPOLL_LISTEN_CNT, EPOLL_LISTEN_TIMEOUT);
for(i = ; i < fd_cnt; i++)
{
sfd = events[i].data.fd;
if(events[i].events & EPOLLIN)
{
if (sfd == g_timerfd)
{
timerfd_handler(sfd);
}
}
}
}
} int epoll_add_fd(int fd)
{
int ret;
struct epoll_event event; memset(&event, , sizeof(event));
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET; ret = epoll_ctl(g_epollfd, EPOLL_CTL_ADD, fd, &event);
if(ret < ) {
LOG_ERROR("epoll_ctl Add fd:%d error, Error:[%d:%s]", fd, errno, strerror(errno));
return -;
} LOG_DEBUG("epoll add fd:%d--->%d success", fd, g_epollfd);
return ;
} int epollfd_init()
{
int epfd; /* create epoll fd */
epfd = epoll_create(EPOLL_LISTEN_CNT);
if (epfd < ) {
LOG_ERROR("epoll_create error, Error:[%d:%s]", errno, strerror(errno));
return -;
}
g_epollfd = epfd;
LOG_DEBUG("epoll fd:%d create success", epfd); return epfd;
} int timerfd_init()
{
int tmfd;
int ret;
struct itimerspec new_value; new_value.it_value.tv_sec = ;
new_value.it_value.tv_nsec = ;
new_value.it_interval.tv_sec = ;
new_value.it_interval.tv_nsec = ; tmfd = timerfd_create(CLOCK_MONOTONIC, );
if (tmfd < ) {
LOG_ERROR("timerfd_create error, Error:[%d:%s]", errno, strerror(errno));
return -;
} ret = timerfd_settime(tmfd, , &new_value, NULL);
if (ret < ) {
LOG_ERROR("timerfd_settime error, Error:[%d:%s]", errno, strerror(errno));
close(tmfd);
return -;
} if (epoll_add_fd(tmfd)) {
close(tmfd);
return -;
}
g_timerfd = tmfd; return ;
} int main(int argc, char **argv)
{
if (epollfd_init() < ) {
return -;
} if (timerfd_init()) {
return -;
} /* event handle */
epoll_event_handle(); return ;
}

参考资料:

http://www.man7.org/linux/man-pages/man2/timerfd_create.2.html

http://blog.csdn.net/walkingman321/article/details/6162055

linux timerfd系列函数总结的更多相关文章

  1. Linux中exec()执行文件系列函数的使用说明

    函数原型: 描述:    exec()系列函数使用新的进程映像替换当前进程映像.    工作方式没有什么差别, 只是参数传递的方式不同罢了. 说明:    1. 这6个函数可分为两大类: execl( ...

  2. Linux Shell系列教程之(十五) Shell函数简介

    本文是Linux Shell系列教程的第(十五)篇,更多Linux Shell教程请看:Linux Shell系列教程 函数可以将一个复杂功能划分成若干模块,从而使程序结构更加清晰,代码重复利用率更高 ...

  3. linux tricks 之VA系列函数.

    VA函数(variable argument function),参数个数可变函数,又称可变参数函数.C/C++编程中,系统提供给编程人员的va函数很少.*printf()/*scanf()系列函数, ...

  4. linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用

    本节目标: exec替换进程映像 exec关联函数组(execl.execlp.execle.execv.execvp) 一,exec替换进程映像 在进程的创建上Unix采用了一个独特的方法,它将进程 ...

  5. posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序

    posix 线程(一):线程模型.pthread 系列函数 和 简单多线程服务器端程序 一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属 ...

  6. c/c++ linux epoll系列3 利用epoll_wait设置timeout时间长度

    linux epoll系列3 利用epoll_wait设置timeout时间长度 epoll_wait函数的第四个参数可以设置,epoll_wait函数的等待时间(timeout时间长度). 例子1, ...

  7. c/c++ linux epoll系列2 利用epoll_wait查看是否可以送信

    linux epoll系列2 利用epoll_wait查看是否可以送信 write函数本来是非阻塞函数,但是当缓存区被写满后,再往缓存区里写的时候,就必须等待缓存区再次变成可写,所以这是write就变 ...

  8. c/c++ linux epoll系列1 创建epoll

    linux epoll系列1 创建epoll 据说select和poll的弱点是,随着连接(socket)的增加,性能会直线下降. epoll不会随着连接(socket)的增加,性能直线下降. 知识点 ...

  9. c/c++ linux 进程间通信系列5,使用信号量

    linux 进程间通信系列5,使用信号量 信号量的工作原理: 由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的: P(sv):如果sv的值大于零,就给它减1:如果 ...

随机推荐

  1. StarUML添加自定义approach和profile

    来源:fasiondog 添加Approch StarUML中的Approch也就是创建项目时的模板,其中预定义了所使用方法的模型和视图.StarUML默认Approach如下: StarUML的Ap ...

  2. eclipse 设置maven来自动下载源码与doc

    通常我们通过maven来使用各种库文件,想要真正了解别人的类实现方法,需要查看别人的源码,maven给我们提供了这个便利,它不仅可以下载各种库文件,还会下载对应的源码和doc文档. 一.在工具栏找到W ...

  3. Unix - 文件中构成一个空洞的分析

    lseek函数显示地为一个打开文件设置偏移量,文件偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将加长该文件,并在文件中构成一个空洞,这一点是允许的.位于文件中但没有写过的字节都被读为 ...

  4. android 防止反编译的若干方法

    第一种方式:混淆策略 混淆策略是每个应用必须增加的一种防护策略,同时他不仅是为了防护,也是为了减小应用安装包的大小,所以他是每个应用发版之前必须要添加的一项功能,现在混淆策略一般有两种: 对代码的混淆 ...

  5. Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!

    Android高效率编码-第三方SDK详解系列(一)--百度地图,绘制,覆盖物,导航,定位,细腻分解! 这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主要还是效率的问题,所以一些有效的东西还 ...

  6. mysql随笔

    MySQL查询优化器--非SPJ的优化 MySQL查询优化器--非SPJ优化(一)--GROUPBY优化 http://blog.163.com/li_hx/blog/static/183991413 ...

  7. CUDA版本的OpenCL在windows 7的下编程初步

    参考文献: http://blog.csdn.net/neoxmu/article/details/8866928 我安装的是CUDA5.5,代码如下: //#include "stdafx ...

  8. 关于linux音频指南

    音频操作是linux系统下必不可少,如您需要设计一个播放器,那么音频就是其中的一部分. 方法/步骤 1 音调: 振动的频率;     音量: 振动的幅度;     音色: 不同介质有不同声音;     ...

  9. opencv基本图像操作

    // Basic_OpenCV_2.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #i ...

  10. rails应用ajax之二:使用rails自身支持

    考虑另一种情况: 1. 页面上半部分显示当前的所有用户,页面下半部分是输入新用户的界面: 2. 每当输入新用户时,页面上半部分会动态更新新加用户的内容: 我们还是用ajax实现,不过这次用rails内 ...