timerfd是Linux为用户程序提供的一个定时器接口。这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景。

一,相关操作函数

#include <sys/timerfd.h>

int timerfd_create(int clockid, int flags);

int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);

int timerfd_gettime(int fd, struct itimerspec *curr_value);

二,timerfd_create

int timerfd_create(int clockid, int flags);

它是用来创建一个定时器描述符timerfd

第一个参数:clockid指定时间类型,有两个值:

CLOCK_REALTIME :Systemwide realtime clock. 系统范围内的实时时钟

CLOCK_MONOTONIC:以固定的速率运行,从不进行调整和复位 ,它不受任何系统time-of-day时钟修改的影响

第二个参数:flags可以是0或者O_CLOEXEC/O_NONBLOCK。

返回值:timerfd(文件描述符)

三,timerfd_settime

在讲解该函数前,先理解两个相关结构体:

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 */
};

第二个结构体itimerspec就是timerfd要设置的超时结构体,它的成员it_value表示定时器第一次超时时间,it_interval表示之后的超时时间即每隔多长时间超时

int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);

作用:用来启动或关闭有fd指定的定时器

参数:

fd:timerfd,有timerfd_create函数返回

fnew_value:指定新的超时时间,设定new_value.it_value非零则启动定时器,否则关闭定时器,如果new_value.it_interval为0,则定时器只定时一次,即初始那次,否则之后每隔设定时间超时一次

old_value:不为null,则返回定时器这次设置之前的超时时间

flags:1代表设置的是绝对时间;为0代表相对时间。

四,timerfd_gettime

int timerfd_gettime(int fd, struct itimerspec *curr_value);

此函数用于获得定时器距离下次超时还剩下的时间。如果调用时定时器已经到期,并且该定时器处于循环模式(设置超时时间时struct itimerspec::it_interval不为0),那么调用此函数之后定时器重新开始计时。

The it_value field returns the amount of time until the timer will next expire. If both fields of this structure are zero, then the timer is currently disarmed. This field always contains a relative value, regardless of whether the TFD_TIMER_ABSTIME flag was specified when setting the timer.

The it_interval field returns the interval of the timer. If both fields of this structure are zero, then the timer is set to expire just once, at the time specified by curr_value.it_value.

五,read读取timefd超时事件通知

read(2) If the timer has already expired one or more times since its settings were last modified using timerfd_settime(), or since the last successful read(2), then the buffer given to read(2) returns an unsigned 8-byte integer (uint64_t) containing the number of expirations that have occurred. (The returned value is in host byte order, i.e., the native byte order for integers on the host machine.)

If no timer expirations have occurred at the time of the read(2), then the call either blocks until the next timer expiration, or fails with the error EAGAIN if the file descriptor has been made nonblocking (via the use of the fcntl(2) F_SETFL operation to set the O_NONBLOCK flag).

A read(2) will fail with the error EINVAL if the size of the supplied buffer is less than 8 bytes.

当定时器超时,read读事件发生即可读,返回超时次数(从上次调用timerfd_settime()启动开始或上次read成功读取开始),它是一个8字节的unit64_t类型整数,如果定时器没有发生超时事件,则read将阻塞若timerfd为阻塞模式,否则返回EAGAIN 错误(O_NONBLOCK模式),如果read时提供的缓冲区小于8字节将以EINVAL错误返回。

 

六,示例代码

man手册中示例:

The following program creates a timer and then monitors its progress. The program accepts up to three command-line arguments. The first argument specifies the number of seconds for the initial expiration of the timer. The second argument specifies the interval for the timer, in seconds. The third argument specifies the number of times the program should allow the timer to expire before terminating. The second and third command-line arguments are optional.

#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* Definition of uint64_t */ #define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0) static void
print_elapsed_time(void)
{
static struct timespec start;
struct timespec curr;
static int first_call = 1;
int secs, nsecs; if (first_call) {
first_call = 0;
if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
handle_error("clock_gettime");
} if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
handle_error("clock_gettime"); secs = curr.tv_sec - start.tv_sec;
nsecs = curr.tv_nsec - start.tv_nsec;
if (nsecs < 0) {
secs--;
nsecs += 1000000000;
}
printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);
} int
main(int argc, char *argv[])
{
struct itimerspec new_value;
int max_exp, fd;
struct timespec now;
uint64_t exp, tot_exp;
ssize_t s; if ((argc != 2) && (argc != 4)) {
fprintf(stderr, "%s init-secs [interval-secs max-exp]\n",
argv[0]);
exit(EXIT_FAILURE);
} if (clock_gettime(CLOCK_REALTIME, &now) == -1)
handle_error("clock_gettime"); /* Create a CLOCK_REALTIME absolute timer with initial
expiration and interval as specified in command line */ new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
new_value.it_value.tv_nsec = now.tv_nsec;
if (argc == 2) {
new_value.it_interval.tv_sec = 0;
max_exp = 1;
} else {
new_value.it_interval.tv_sec = atoi(argv[2]);
max_exp = atoi(argv[3]);
}
new_value.it_interval.tv_nsec = 0; fd = timerfd_create(CLOCK_REALTIME, 0);
if (fd == -1)
handle_error("timerfd_create"); if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
handle_error("timerfd_settime"); print_elapsed_time();
printf("timer started\n"); for (tot_exp = 0; tot_exp < max_exp;) {
s = read(fd, &exp, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read"); tot_exp += exp;
print_elapsed_time();
printf("read: %llu; total=%llu\n",
(unsigned long long) exp,
(unsigned long long) tot_exp);
} exit(EXIT_SUCCESS);
}

运行结果:

linux新定时器:timefd及相关操作函数的更多相关文章

  1. (二十四)linux新定时器:timefd及相关操作函数

    timerfd是Linux为用户程序提供的一个定时器接口.这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景. 一,相关操作函数 #inclu ...

  2. python字符串 列表 元组 字典相关操作函数总结

    1.字符串操作函数 find 在字符串中查找子串,找到首次出现的位置,返回下标,找不到返回-1 rfind 从右边查找 join 连接字符串数组 replace 用指定内容替换指定内容,可以指定次数 ...

  3. 尚学linux课程---9、yum相关操作和知识

    尚学linux课程---9.yum相关操作和知识 一.总结 一句话总结: 如何使用比如163,阿里云给yum配置yum源:去官网,不要百度:直接去官网,有帮助文档的(比如centos的就在centos ...

  4. 关于php的ini文件相关操作函数浅析

    在小公司,特别是创业型公司,整个服务器的搭建一般也是我们 PHP 开发工程师的职责之一.其中,最主要的一项就是要配置好服务器的 php.ini 文件.一些参数会对服务器的性能产生深远的影响,而且也有些 ...

  5. 【原创】Linux基础之gz文件相关操作

    gz文件不需要解压即可进行相关操作 $ zcat test.log.gz $ zmore test.log.gz $ zless test.log.gz $ zgrep '1.2.3.4' test. ...

  6. Linux中与环境变量相关的函数

    1.在终端可以通过env.set命令查看当前的环境变量 2.通过main函数中的第三个参数可以得到当前进程的环境变量列表 int main(int argc , char *argv[] , char ...

  7. 关于Linux下软件包aptitude的相关操作

    aptitude+回车 - 进入aptitude操作界面,可以对预览查看各种软件包 aptitude show package_name - 列出与XXX相关的软件包信息,但是并不能看到该软件包所安装 ...

  8. 【php】php数组相关操作函数片段

    下面这些都是我在工作中用到的函数,现在整理下. 判断是否是一个数组 function _is_array($value){ if (is_array($value)) { return true; } ...

  9. Python3中dict字典的相关操作函数

    字典对象的内建函数 1. clear() 清空字典. 例: >>> a = {1:3, 2:4} >>> a.clear() >>> a {} 2 ...

随机推荐

  1. jdbcTemplate in

    参考 http://blog.csdn.net/gaopeng0071/article/details/75049952 使用NamedParameterJdbcTemplate public cla ...

  2. stuff函数(转)

    在上篇博文中提到了stuff函数 在这篇博文中对stuff函数进行了详解 本片博文系转载,但对原文顺序做了下调整 示例 以下示例在第一个字符串 abcdef 中删除从第 2 个位置(字符 b)开始的三 ...

  3. 【Spring】Spring boot多数据源历险记

    一.问题描述 笔者根据需求在开发过程中,需要在原项目的基础上(单数据源),新增一个数据源C,根据C数据源来实现业务.至于为什么不新建一个项目,大概是因为这只是个小功能,访问量不大,不需要单独申请个服务 ...

  4. js string 字符串

    mutil lines string 多行字符串, 由于多行字符串用\n写起来比较费事,所以最新的ES6标准新增了一种多行字符串的表示方法,用...表示,是单撇号, 不是单引号. 这是一个 多行 字符 ...

  5. B/S与C/S的比较

    1.C/S需要安装客户端软件,比如我们的qq就是C/S模式下的软件.如果使用这些软件我们必须先要下载客户端软件.如果软件更新了,就需要下载新的客户端进行更新. 2.B/S无需安装客户端软件,比如我们的 ...

  6. IDEA 的VM Option设置加快页面的加载速度

    VM Option的设置: -Xms1024M -Xmx2048M -XX:PermSize=128M -XX:MaxPermSize=256M

  7. Ubuntu 下如何查看已安装的软件

    1.查看安装的所有软件 dpkg -l 例如:dpkg -l | grep ftp <span style="font-size:18px;">:~$ dpkg -l ...

  8. msys2 启用windows PATH环境变量

    有三种方法修改 ①msys2_shell.cmd 中取消一行的注释:set MSYS2_PATH_TYPE=inherit ②调用msys2_shell.cmd时使用-use-full-path参数 ...

  9. android 弹出软键盘将底部视图顶起问题

    今天要做一个搜索功能,搜索界面采用AutoCompleteTextView做搜索条,然后下面用listview来显示搜索结果,而我的主界面是在底 部用tab做了一个主界面导航,其中有一个搜索按钮,因为 ...

  10. 人类基因组三代组装: cano

    git clone https://github.com/marbl/canu.git cd canu/src make -j <number of threads> 使用实例: canu ...