特点

Linux 内核于内核2.6.25提供了一种创建定时器的 API, 那就是 Linux 特有的 timerfd API, 并且该定时器可以从文件描述符中读取其创建的定时器到期通知.

这也意味着, 可以将文件描述符通过多路复用监听并读取, 而其他的定时器想要将一个 (或多个) 定时器与一组文件描述符放在一起同时监听可不是一件容易的事.


函数接口

timerfd 系列 API 有三个系统调用 :

  • 第一个系统调用, 该系统调用创建一个新的定时器对象 :
#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);
//成功返回一个指代该对象的文件描述符, 失败返回-1及errno

第一个参数 clockid 可以设置为 CLOCK_REALTIMECLOCK_MONOTONIC

CLOCK_REALTIME
可设定的系统级实时时钟.
相对时间,从1970.1.1到目前的时间。更改系统时间会更改获取的值。也就是说,它以系统时间为坐标。

CLOCK_REALTIME 用于度量真实时间, 他的设置可以变更

CLOCK_MONOTONIC
不可设定的恒定态时钟
与CLOCK_REALTIME相反,它是以绝对时间为准,获取的时间为系统重启到现在的时间,更改系统时间对齐没有影响。

CLOCK_MONOTONIC 时钟适用于那些无法容忍系统时钟发生跳跃性变化(如, 手动改变了系统时间)的应用上

第二个参数flags, 支持 TFD_CLOEXECTFD_NONBLOCK0
TFD_CLOEXEC 为新的文件描述符设置运行时关闭标志 (FD_CLOEXEC)
TFD_NONBLOCK 为底层的打开文件描述符设置 O_NONBLOCK 标志, 随后的读操作将是非阻塞的, 这与调用 fcntl 效果相同

使用完定时器要记得 close


  • 第二个系统调用, 可以启动或停止由文件描述符 fd 所指代的定时器
#include <sys/timerfd.h>int timerfd_settime(int fd, int flags, const struct itimerspec* new_value, struct itimerspec* old_value);
//成功返回0, 失败返回-1和 errno

flags 的值可以是 0 (相对时间), 可以是 TFD_TIMER_ABSTIME (绝对时间)

而第二第三个参数都是struct itimerspec* 类型

struct itimerspec
{struct timespec it_interval;   //间隔时间struct timespec it_value;      //第一次到期时间
};struct timespec
{time_t tv_sec;    //秒long tv_nsec;    //纳秒
}; 

new_value 为定时器指定新设置, old_value 用来返回定时器的前一设置, 如果不关心, 可将其设置为 NULL
new_value: 指定新的超时时间,若 newValue.it_value非 0 则启动定时器,否则关闭定时器。若 newValue.it_interval 为 0 则定时器只定时一次,否则之后每隔设定时间超时一次。
old_value:不为 NULL 时则返回定时器这次设置之前的超时时间。

timerfd_create第一个参数和 clock_gettime(获取时间的函数,下面介绍) 的第一个参数都是 CLOCK_REALTIME 或者 CLOCK_MONOTONIC,timerfd_settime 的第二个参数为0(相对时间)或者 TFD_TIMER_ABSTIME(绝对时间)

  • 如果 timerfd_settime 设置为 TFD_TIMER_ABSTIME(绝对时间),则后面的时间必须用 clock_gettime 来获取,获取时设置 CLOCK_REALTIME 还是 CLOCK_MONOTONIC 取决于 timerfd_create 设置的值。
  • 如果 timerfd_settime 设置为 0(相对定时器),则后面的时间必须用相对时间

  • 第三个系统调用, 返回文件描述符 fd 所标识定时器的间隔及剩余时间
#include <sys/timerfd.h>
int timerfd_gettime(int fd, struct itimerspec *curr_value);
//成功返回0, 失败返回-1和errno

间隔和距离下次到期的时间均返回到 curr_value 指向的结构体.
如果返回的结构中 curr_value.it_value 中所有字段值均为0, 那么该定时器已经解除, 如果返回的结构 curr_value.it_interval 中两字段值均为0, 那么该定时器只会到期一次, 到期时间在 curr_value.it_value 中给出


  • 获取时钟的值
#include <time.h>
int clock_gettime(clockid_t clk_id, struct timespect *tp);

使用 epoll 监听定时器到期事件

#include <sys/timerfd.h>
#include <iostream>
#include <time.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <assert.h>
using namespace std;const int MAXNUM = 20;int main(int argc, char *argv[])
{struct itimerspec new_value;struct timespec now;uint64_t exp;ssize_t s;int ret = clock_gettime(CLOCK_REALTIME, &now);//获取时钟时间assert(ret != -1);new_value.it_value.tv_sec = 5; //第一次到期的时间new_value.it_value.tv_nsec = now.tv_nsec; new_value.it_interval.tv_sec = 1;      //之后每次到期的时间间隔new_value.it_interval.tv_nsec = 0;int timefd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK); // 构建了一个定时器assert(timefd != -1);ret = timerfd_settime(timefd, 0, &new_value, NULL);//启动定时器assert(ret != -1);cout << "timer started" << endl; // 定时器开启啦!int epollfd = epoll_create(1);  //创建epoll实例对象struct epoll_event ev;struct epoll_event events[MAXNUM];ev.data.fd = timefd;ev.events = EPOLLIN | EPOLLET;epoll_ctl(epollfd, EPOLL_CTL_ADD, timefd, &ev); //添加到epoll事件集合for (; ;) {int num = epoll_wait(epollfd, events, MAXNUM, 0);assert(num >= 0);for (int i = 0; i < num; i++) {if (events[i].events & EPOLLIN) {//....处理其他事件if (events[i].data.fd == timefd) {s = read(events[i].data.fd, &exp, sizeof(uint64_t)); //需要读出uint64_t大小, 不然会发生错误assert(s == sizeof(uint64_t));cout << "here is timer" << endl;}}}}close(timefd);close(epollfd);return 0;
}

注意

timerfd_settime第二个参数如果是 0, 是相对时间, 如果是 TFD_TIMER_ABSTIME, 代表绝对时间, 但是这里还有需要注意的点

By default, the initial expiration time specified in new_value is interpreted relative to the current time on the timer’s clock at the time of the call (i.e., new_value.it_value specifies a time relative to the current value of the clock specified by clockid).


默认情况下, new_value中指定的初始过期时间相对于调用时计时器时钟上的当前时间(即, new_value.it_value 指定相对于 clockid 指定的时钟的当前值的时间)。

也就是说
new_value.it_value设置初次到期的时间firsttime

如果timerfd_settime第二个参数设置为 0, new_value.it_value = firsttime
如果timerfd_settime第二个参数设置为TFD_TIMER_ABSTIME,new_value.it_value = now.tv_sec + firsttime

使用 Linux下 timerfd 系列 API 创建定时器并使用 epoll 监听相关推荐

  1. Linux下 timerfd创建定时器并使用 epoll 监听

    介绍:Linux系统提供了timerfd系列的定时函数,其具体函数名如下 #include <sys/timerfd.h>int timerfd_create(int clockid, i ...

  2. linux oracle 用户创建,LINUX下Oracle数据库用户创建方法详解

    本文实例分析了LINUX下Oracle数据库用户创建方法.分享给大家供大家参考,具体如下: 1)登录linux,以oracle用户登录(如果是root用户登录的,登录后用 su - oracle命令切 ...

  3. Delphi 下用Windows API 创建窗体

    Delphi 下用Windows API 创建窗体 副标题: 作者:佚名 文章来源:大富翁 点击数:119 更新时间:2005-2-25     Delphi 下用Windows API 创建窗体 / ...

  4. linux 下通过 httpd服务创建网页

    linux 下通过 httpd服务创建网页 1.安装httpd服务 yum install httpd -y [root@node143 ~]# yum install httpd -y 2.查看防火 ...

  5. linux epoll监听套接字实例

    linux epoll机制用于IO多路复用,能够同时监听多个接字,使用起来比较简单. 相关接口: #include <sys/epoll.h>int epoll_create(int si ...

  6. Linux oracle(常用命令)启动、停止、监听

    Linux oracle(常用命令)启动.停止.监听 1.手动启动 dbstart /u01/app/oracle/product/11.2.0/dbhome_1 (ORACLE_HOME) 2.停止 ...

  7. oracle12541 linux,PLSQL连接Linux上的oracle数据库出现,ORA-12541 TNS 无监听程序

    PLSQL连接Linux上的oracle数据库出现,ORA-12541 TNS 无监听程序 外部的PLSQL无法连接Linux上的oracle数据库,出现ORA-12541 TNS 无监听程序错误.待 ...

  8. 如何在Linux下使用Gitblit工具创建Git仓库服务

    嗨!朋友,今天我们将学习如何在你的Linux服务器或者PC上安装Gitblit工具.首先,我们看看什么是Git,它的功能以及安装Gitblit的步骤.Git是分布式版本控制系统,它强调速度.数据一致性 ...

  9. linux下文件夹的创建、复制、剪切、重命名、清空和删除命令

    在home目录下有wwwroot目录,wwwroot下有sinozzz目录,即/home/wwwroot/sinozzz 一.目录创建 在/home/wwwroot目录下新建一个sinozzz123的 ...

  10. Linux下动态库的创建与更新

    Linux下动态库(libname.x.y.z)的创建与更新 由于主程序和它依赖的共享库是由不同的开发者开发的.共享库的开发者会不停地更新共享库的版本,以修正bug,增加功能或改进性能.版本多了之后, ...

最新文章

  1. Journey源码分析三:模板编译
  2. Extjs Form用法详解(适用于Extjs5)
  3. HoughLines 函数
  4. python 左旋转字符串
  5. MCtalk教育快报 | 0824
  6. hibernate mysql 关联查询_Hibernate关联映射及高级查询
  7. python解复杂方程组_sympy计算方程组的复杂表达式怎么获得数值解?
  8. secure连不上远程地址_[笔记]Mariadb安装并配置远程访问
  9. c2065c语言错误,C语言常见错误
  10. python好用的软件_新手写Python程序有什么推荐好用编辑器
  11. 用WPS2000制作勾股定理教学课件(转)
  12. matlab计算正弦信号基波,Matlab入门篇——正弦信号、实指数信号和复指数信号的仿真.ppt...
  13. Linux基础加实际操作演示
  14. 微信账单动态吸顶功能实现逻辑
  15. linux中跳板机的部署
  16. XDL-(1)Linux文件操作命令
  17. matlab中webcam,MATLAB编程-MATLAB2014a的webcam操作
  18. 【JY】结构工程师:请避开有限元分析中6个常见的“坑”
  19. 360强行卸载金山网盾 致大量用户系统异常
  20. 软碟通 制作系统启动u盘

热门文章

  1. 破译密码、设计飞机和建设团队:Randy Shoup谈高绩效团队
  2. 物联网领域不断扩展,ATT很“兴奋”
  3. hashmap和hashtable,arraylist和vector的区别
  4. 如何修改Myeclipse的JSP模板
  5. 关于网上商城开发的随笔记录1
  6. Extjs study
  7. System.Trunc、System.Round、System.Int - 返回整数部分
  8. 5.携程架构实践 --- 框架中间件
  9. 14.PHP vld 扩展
  10. 4.ES 相关插件安装