timerfd periodik dapat mengalami beberapa ekspirasi sebelum user space membacanya. read() sukses berikutnya tidak hanya melaporkan tick terbaru: operasi itu mengembalikan nilai unsigned 64-bit yang berisi jumlah ekspirasi sejak read sukses sebelumnya, atau sejak timer dikonfigurasi jika belum ada read yang selesai.

Perilaku ini menjadikan timer sebagai objek event loop tanpa mengubah setiap ekspirasi menjadi signal. Descriptor menjadi readable ketika sedikitnya satu ekspirasi tertunda, dan descriptor yang sama dapat dipantau oleh poll(), select(), atau epoll() bersama socket, pipe, dan sumber event berbasis descriptor lainnya.

Readiness merepresentasikan ekspirasi yang tertunda

timerfd_create() membuat objek timer dan mengembalikan file descriptor yang merujuk kepadanya. timerfd_settime() kemudian mengaktifkan atau menonaktifkan timer tersebut serta dapat mengatur ekspirasi one-shot maupun interval berulang.

Setelah satu atau beberapa ekspirasi terjadi, descriptor menjadi readable. read() yang sukses mengonsumsi jumlah ekspirasi tertunda dan menyalin nilai uint64_t dalam host byte order ke user space. Buffer harus berukuran sedikitnya delapan byte.

Pada descriptor nonblocking, read tanpa ekspirasi tertunda gagal dengan EAGAIN. Blocking read menunggu sampai terjadi ekspirasi. Dengan demikian, readiness polling dan read langsung memakai batas pending-event yang sama.

uint64_t expirations;

ssize_t n = read(timer_fd, &expirations, sizeof(expirations));
if (n == sizeof(expirations)) {
    handle_expirations(expirations);
}

Jumlah tersebut penting ketika scheduling latency atau pekerjaan lain membuat proses tidak sempat melayani descriptor pada setiap interval. Nilai lebih besar dari satu mencatat bahwa beberapa periode timer telah berlalu sebelum dikonsumsi.

Clock yang dipilih menentukan progres timer

clockid yang diberikan ke timerfd_create() menentukan basis waktu. CLOCK_MONOTONIC bergerak monoton tetapi tidak memasukkan waktu saat sistem berada dalam kondisi suspend. CLOCK_BOOTTIME juga monoton dan memasukkan waktu suspend.

CLOCK_REALTIME mengikuti wall clock yang dapat diubah. Semantiknya berbeda dari clock monoton ketika waktu sistem berubah secara diskontinu. Varian alarm dapat membangunkan sistem yang sedang suspend, dengan syarat capability CAP_WAKE_ALARM tersedia.

Properti clock tersebut berasal dari clock Linux yang dipilih, bukan dari mekanisme readiness descriptor. timerfd mengekspos status ekspirasi melalui descriptor sambil mempertahankan semantik clock yang dikonfigurasi.

Deadline relatif dan absolut memakai descriptor yang sama

Secara default, timerfd_settime() menafsirkan it_value relatif terhadap nilai saat ini dari clock timer. Dengan TFD_TIMER_ABSTIME, it_value menyatakan titik absolut pada clock tersebut.

Interval tidak bergantung pada pilihan itu. it_interval yang bukan nol menghasilkan ekspirasi berulang setelah deadline awal, sedangkan interval nol membuat timer bersifat one-shot. it_value nol menonaktifkan timer.

struct itimerspec spec = {
    .it_value = { .tv_sec = 2, .tv_nsec = 0 },
    .it_interval = { .tv_sec = 1, .tv_nsec = 0 },
};

timerfd_settime(timer_fd, 0, &spec, NULL);

Konfigurasi ini pertama kali berekspirasi setelah dua detik, lalu setiap satu detik berdasarkan clock timer. Jika tiga ekspirasi periodik tertunda sebelum read sukses berikutnya, read tersebut dapat mengembalikan 3 tanpa memerlukan tiga event readiness terpisah.

Pembatalan akibat wall clock bersifat eksplisit

Timer absolut berbasis CLOCK_REALTIME atau CLOCK_REALTIME_ALARM dapat memakai TFD_TIMER_CANCEL_ON_SET bersama TFD_TIMER_ABSTIME. Perubahan diskontinu pada real-time clock kemudian menandai timer sebagai canceled, dan read() saat ini atau berikutnya melaporkan ECANCELED.

Mekanisme tersebut memisahkan diskontinuitas clock dari ekspirasi biasa. Perangkat lunak yang memakai deadline wall-clock dapat memperlakukan penggantian clock sebagai transisi status, bukan menerima deadline yang dihitung terhadap pemetaan wall clock sebelumnya secara diam-diam.

Flag pembatalan ini tidak berlaku secara umum untuk semua clock timerfd. Penggunaan yang didokumentasikan terikat pada timer absolut dengan varian real-time clock.

Lifetime descriptor mengikuti semantik file melintasi proses

Setelah fork(), descriptor yang diwariskan merujuk ke objek timer dasar yang sama dengan descriptor terkait pada parent. Read dari salah satu proses mengamati ekspirasi dari objek timer bersama tersebut.

Saat execve(), descriptor timer tetap terbuka kecuali close-on-exec diaktifkan. TFD_CLOEXEC dapat diberikan saat pembuatan agar descriptor ditutup secara atomik selama transisi exec yang sukses.

Ketika semua descriptor yang merujuk ke objek timer telah ditutup, kernel menonaktifkan timer dan melepaskan resource-nya. Model lifetime ini membuat kepemilikan timer mengikuti kepemilikan descriptor, bukan registrasi signal terpisah.

Jumlah ekspirasi menyimpan event waktu, bukan slot eksekusi

Timer periodik tidak menyediakan satu eksekusi callback yang dicadangkan untuk setiap interval. Timer mencatat ekspirasi, mengekspos readiness, lalu read mengambil jumlah yang terakumulasi. Kode event loop dapat menentukan apakah nilai lima berarti lima unit pekerjaan, satu pembaruan yang digabungkan, atau kondisi missed deadline.

Pemisahan tersebut merupakan sifat penting timerfd: progres timer di kernel dan cadence pelayanan di user space tetap terpisah. Readiness descriptor menandakan status tertunda, sedangkan nilai 64-bit dari read mempertahankan jumlah ekspirasi yang direpresentasikan oleh status itu.