timerfd_create 函数简介
timerfd_create 是 Linux 提供的一个系统调用,用于创建一个文件描述符,用来触发定时器事件。可以通过该文件描述符来监视定时器到期事件,例如用 poll 或 select 进行事件检测。这种机制常用于高效的事件驱动型程序。
函数原型
#include <sys/timerfd.h>
int timerfd_create(int clockid, int flags);
clockid: 指定定时器使用的时钟,可以是以下值:CLOCK_REALTIME: 基于系统的实时时钟,受系统时间改变影响。CLOCK_MONOTONIC: 基于系统的单调时钟,不受系统时间改变影响。
flags: 指定文件描述符的行为,常用值:0: 默认行为。TFD_NONBLOCK: 非阻塞模式。TFD_CLOEXEC:exec时自动关闭文件描述符。
返回值:
- 成功时返回定时器文件描述符(一个正整数)。
- 失败时返回
-1,并设置errno。
定时器设置:timerfd_settime
要设置定时器,可以使用以下函数:
#include <sys/timerfd.h>
int timerfd_settime(int fd, int flags,
const struct itimerspec *new_value,
struct itimerspec *old_value);
fd: 使用timerfd_create创建的文件描述符。flags: 通常为0。若设置为TFD_TIMER_ABSTIME,则定时器以绝对时间计算。new_value: 指定定时器的新值,使用struct itimerspec结构。old_value: 如果不为NULL,则保存定时器的旧值。
struct itimerspec 结构:
struct itimerspec {
struct timespec it_interval; // 定时器的间隔时间
struct timespec it_value; // 定时器的初始到期时间
};
示例代码
以下代码展示了如何使用 timerfd_create 创建一个定时器,并通过 poll 等待定时器事件:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include <sys/poll.h>
#include <time.h>
#include <stdint.h> // for uint64_t
int main() {
int timer_fd;
struct itimerspec new_timer;
// 创建一个基于单调时钟的定时器
timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
if (timer_fd == -1) {
perror("timerfd_create failed");
exit(EXIT_FAILURE);
}
// 设置定时器:2秒后触发,然后每隔1秒触发一次
new_timer.it_value.tv_sec = 2; // 首次触发的时间(秒)
new_timer.it_value.tv_nsec = 0; // 首次触发的时间(纳秒)
new_timer.it_interval.tv_sec = 1; // 每次触发的间隔时间(秒)
new_timer.it_interval.tv_nsec = 0; // 每次触发的间隔时间(纳秒)
if (timerfd_settime(timer_fd, 0, &new_timer, NULL) == -1) {
perror("timerfd_settime failed");
exit(EXIT_FAILURE);
}
printf("Timer started! It will fire in 2 seconds, then every 1 second.\n");
// 使用 poll 监视定时器文件描述符
struct pollfd poll_fds;
poll_fds.fd = timer_fd;
poll_fds.events = POLLIN; // 等待定时器可读事件
while (1) {
int ret = poll(&poll_fds, 1, -1); // 无限等待
if (ret == -1) {
perror("poll failed");
exit(EXIT_FAILURE);
}
if (poll_fds.revents & POLLIN) {
uint64_t expirations;
ssize_t s = read(timer_fd, &expirations, sizeof(expirations));
if (s != sizeof(expirations)) {
perror("read failed");
exit(EXIT_FAILURE);
}
printf("Timer expired %llu times\n", (unsigned long long) expirations);
}
}
close(timer_fd);
return 0;
}
代码说明
- 创建定时器:
- 使用
timerfd_create创建一个基于CLOCK_MONOTONIC的定时器。
- 使用
- 设置定时器:
- 使用
timerfd_settime设置首次触发时间为 2 秒,之后每隔 1 秒触发一次。
- 使用
- 等待定时器事件:
- 使用
poll等待定时器文件描述符的可读事件。 - 每当定时器触发,文件描述符变为可读,通过
read读取定时器触发的次数。
- 使用
- 输出结果:
- 每次定时器触发时,输出触发的次数。
示例运行
运行上述代码,输出如下:
Timer started! It will fire in 2 seconds, then every 1 second.
Timer expired 1 times
Timer expired 1 times
Timer expired 1 times
...
优点
- 可以高效地监控多个定时器文件描述符,与
epoll或poll配合使用适合事件驱动编程。 - 使用单调时钟(
CLOCK_MONOTONIC)不受系统时间修改的影响,非常适合定时任务。
注意事项
- 文件描述符需要在程序结束时关闭(
close)。 - 定时器间隔为
0时,表示单次触发定时器。



















