简介
- timerfd 接口是Linux内核从版本2.6开始提供的定时器接口,非常适合用来实现应用层定时器模块
优点
- 在内核中采用高精度定时器不同于sleep等延时函数,时间精度非常高
- 使用简单,时间处理在内核实现,应用层不需要太多处理
- 接口基于文件描述符,适合 select/poll/epoll管理
接口说明
头文件
sys/timerfd.h
创建定时器
int timerfd_create(int clockid, int flags);
- CLOCK_REALTIME :Systemwide realtime clock. 实时时钟,真实的时间
- CLOCK_MONOTONIC:系统启动后开始计时,从不进行调整和复位,不受系统时钟修改的影响
- flags可以是0或者O_CLOEXEC/O_NONBLOCK。
- 返回值:timerfd(文件描述符)
定时器设置
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);
- fd: 参数fd是timerfd_create函数返回的文件句柄
- flags:有两选项 0或1
- TFD_TIMER_ABSTIME 表示绝对时间,例如:若clockid填的是CLOCK_MONOTONIC,TFD_TIMER_ABSTIME表示启动后 it_value 时间,
- 0 表示相对时间, 例如:若clockid填的是CLOCK_MONOTONIC,flags为0 表示当前时间后it_value时间,
- new_value: 参数new_value指定定时器的超时时间以及超时间隔时间
- old_value: 如果old_value不为NULL, old_vlaue返回之前定时器设置的时间参数
Tips: - it_interval不为0则表示是周期性定时器。
- it_value和it_interval都为0表示停止定时器
定时器获取下次超时剩余的时间
int timerfd_gettime(int fd, struct itimerspec *curr_value);
- curr_value.it_value 字段表示距离下次超时的时间,如果该值为0,表示计时器已经解除; 该字段表示的值永远是一个相对值,无论TFD_TIMER_ABSTIME是否被设置
- curr_value.it_interval 定时器间隔时间
定时器fd 读取
uint64_t exp = 0;
read(fd, &exp, sizeof(uint64_t));
定时器关闭
close(fd);
- 可以先通过 timerfd_settime 停止定时器
注意点
- timerfd_create 第一个参数 clockid 和 timerfd_settime 的第二个参数 flags 很容易误导
- 如果timerfd_settime设置为TFD_TIMER_ABSTIME(绝对时间),则设置的时间是具体的某个时间点, clock_gettime获取当前时间加上时间差,获取时设置CLOCK_REALTIME还是CLOCK_MONOTONIC取决于timerfd_create设置的值。
- 如果timerfd_settime设置为0(相对时间),则设置的时间是相对与当前的时间,例如:
new_value.it_value.tv_sec = 3;
new_value.it_value.tv_nsec = 0;
例子