timerfd_create(2)
Create a timer that reports expirations through a readable file descriptor.
- Since
- Linux 2.6.25check your kernel →
- glibc
- glibc 2.8
- System
- Linux
- Man page
- timerfd_create(2)
Synopsis
#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 *_Nullable old_value);
int timerfd_gettime(int fd, struct itimerspec *curr_value);Rod's take
SIGALRM plus setitimer means a handler firing at some arbitrary point in your code to flip a global you'll check later. Garbage, and always was. timerfd makes the timer a file descriptor: it goes readable when it fires, and read() hands back a 64-bit count of expirations, so a slow loop finds out it missed three ticks instead of silently losing them. CLOCK_MONOTONIC for intervals; CLOCK_REALTIME only for wall-clock deadlines, with TFD_TIMER_ABSTIME. Then drop it in epoll next to everything else and stop thinking about signals.
Flags and arguments that matter
| Name | What it does |
|---|---|
| CLOCK_MONOTONIC | Nonsettable monotonic clock; the right choice for intervals. |
| CLOCK_REALTIME | Settable wall clock; use with TFD_TIMER_ABSTIME for wall-clock deadlines. |
| CLOCK_BOOTTIMELinux 3.15 | Like CLOCK_MONOTONIC but keeps counting while the system is suspended. |
| CLOCK_REALTIME_ALARM / CLOCK_BOOTTIME_ALARMLinux 3.11 | Wake the system from suspend; setting requires CAP_WAKE_ALARM. |
| TFD_NONBLOCKLinux 2.6.27 | Set O_NONBLOCK on the new descriptor. |
| TFD_CLOEXECLinux 2.6.27 | Set close-on-exec on the new descriptor. |
| TFD_TIMER_ABSTIME | timerfd_settime(): treat it_value as an absolute time on the timer's clock. |
| TFD_TIMER_CANCEL_ON_SET | With ABSTIME on a REALTIME clock: read(2) fails with ECANCELED if the clock jumps. |
| TFD_IOC_SET_TICKSLinux 3.17 | ioctl(2) to set the expiration count; for checkpoint/restore. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EINVAL | clockid is not valid, or flags is invalid. |
| EPERM | An *_ALARM clock was requested without CAP_WAKE_ALARM. |
| EMFILE | Per-process open file descriptor limit reached. |
| ENOMEM | Insufficient kernel memory to create the timer. |
| ECANCELED | timerfd_settime()/read(2): TFD_TIMER_CANCEL_ON_SET timer and the real-time clock changed. |
Example
int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if (tfd < 0)
err(1, "timerfd_create");
struct itimerspec its = {
.it_interval = { .tv_sec = 5 }, /* repeat every 5s */
.it_value = { .tv_sec = 5 }, /* first fire in 5s */
};
if (timerfd_settime(tfd, 0, &its, NULL) < 0)
err(1, "timerfd_settime");
/* when epoll says readable: */
uint64_t expirations;
if (read(tfd, &expirations, sizeof(expirations)) == sizeof(expirations))
do_periodic_work(expirations);Trimmed from the full walkthrough in timerfd, signalfd, eventfd: every event source is a file descriptor now.
BSD equivalent
FreeBSD: native timerfd(2) (FreeBSD 14.0), or EVFILT_TIMER in kqueue(2). OpenBSD: EVFILT_TIMER in kqueue(2).
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
