赞
踩
timerfd是Linux为用户程序提供的一个定时器接口。
这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景。
These system calls create and operate on a timer that delivers timer expiration notifications via a file descriptor.
这三个系统调用创建并操作计时器,该计时器通过文件描述符传递计时器过期通知。
#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);
创建一个定时器描述符timerfd
int timerfd_settime(int fd, int flags,
const struct itimerspec *new_value,
struct itimerspec *old_value);
用来启动或关闭有fd指定的定时器
int timerfd_gettime(int fd, struct itimerspec *curr_value);
此函数用于获得定时器距离下次超时还剩下的时间。
fd timerfd_create的返回值
flags:1代表设置的是绝对时间;为0代表相对时间。
The flags argument is either 0, to start a relative timer , or TFD_TIMER_ABSTIME, to start an absolute timer
new_value 指定新的超时时间
设定new_value.it_value非零则启动定时器,否则关闭定时器,如果new_value.it_interval为0,则定时器只定时一次,即初始那次,否则之后每隔设定时间超时一次
old_value:不为null,则返回定时器这次设置之前的超时时间
一般为0
结构 itimerspec 定义
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 */
};
#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); }
说明:
main接收1个或3个参数
参数含义分别是:初始超时时间,间隔超时时间,超时次数
read读取timefd超时事件通知
当定时器超时,read读事件发生即可读,返回超时次数(从上次调用timerfd_settime()启动开始或上次read成功读取开始),它是一个8字节的unit64_t类型整数,如果定时器没有发生超时事件,则read将阻塞若timerfd为阻塞模式,否则返回EAGAIN 错误(O_NONBLOCK模式),如果read时提供的缓冲区小于8字节将以EINVAL错误返回。
结果:
[root@glusterfs home]# ./a.out 2 1 5
0.000: timer started
1.1000: read: 1; total=1
2.1000: read: 1; total=2
3.1000: read: 1; total=3
5.000: read: 1; total=4
6.000: read: 1; total=5
[root@glusterfs home]#
[root@glusterfs home]# ./a.out 2
0.000: timer started
1.1000: read: 1; total=1
[root@glusterfs home]#
https://www.cnblogs.com/mickole/p/3261879.html
https://man7.org/linux/man-pages/man2/timerfd_create.2.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。