timerfd periodik tidak memerlukan satu wakeup userspace untuk setiap ekspirasi timer. Jika beberapa ekspirasi terjadi sebelum descriptor dibaca, Linux mengakumulasikannya dan mengembalikan jumlahnya dalam satu integer 8 byte.
Perilaku ini menempatkan state timer dalam model readiness yang sama dengan socket, pipe, dan descriptor lain. Event loop yang terlambat juga memperoleh informasi eksplisit tentang periode yang terlewat, alih-alih beberapa ekspirasi dilebur menjadi satu notifikasi.
State ekspirasi menjadi data descriptor yang dapat dibaca
timerfd_create() membuat objek timer dan mengembalikan file descriptor yang merujuk kepadanya. Clock yang dipilih menentukan basis waktu timer. Pilihan umum mencakup CLOCK_MONOTONIC, CLOCK_REALTIME, dan CLOCK_BOOTTIME.
timerfd_settime() mengaktifkan atau menonaktifkan timer. it_value yang bukan nol menetapkan ekspirasi pertama; it_interval yang bukan nol membuat ekspirasi berikutnya periodik. Tanpa TFD_TIMER_ABSTIME, it_value bersifat relatif terhadap nilai clock saat pemanggilan. Dengan flag tersebut, nilainya merupakan nilai clock absolut.
Setelah satu atau beberapa ekspirasi tertunda, descriptor menjadi readable melalui poll(), select(), atau epoll. read() yang berhasil menghasilkan uint64_t dalam byte order host yang berisi jumlah ekspirasi sejak read berhasil sebelumnya atau sejak perubahan setting timer terakhir.
uint64_t expirations;
ssize_t n = read(timer_fd, &expirations, sizeof(expirations));
if (n == sizeof(expirations)) {
process_ticks(expirations);
}Buffer harus berukuran sedikitnya 8 byte. Pada descriptor nonblocking, read tanpa ekspirasi tertunda gagal dengan EAGAIN.
Timer periodik mempertahankan informasi overrun
Ambil timer dengan interval 100 ms. Jika event loop sibuk selama 470 ms setelah read berhasil, beberapa periode dapat berlalu sebelum descriptor dilayani kembali. Read berikutnya dapat menghasilkan nilai lebih besar dari satu.
Jumlah tersebut adalah state operasional, bukan sekadar sinyal readiness. Program dapat memakainya untuk memajukan penghitung tick logis, mencatat periode sampling yang terlewat, atau mendeteksi bahwa latensi pemrosesan melampaui cadence timer.
Loop yang mengabaikan nilai hasil dan menganggap satu tick untuk setiap read membuang informasi ini:
uint64_t expirations;
if (read(timer_fd, &expirations, sizeof(expirations)) == sizeof(expirations)) {
logical_tick += expirations;
}Kernel tidak menjamin userspace berjalan tepat pada setiap deadline yang diminta. Latensi scheduling dan beban sistem dapat menunda observasi. Penghitung ekspirasi mencatat berapa banyak event timer yang berlalu sebelum userspace mengonsumsi state tersebut.
Pilihan clock mengubah semantik suspend dan wall-clock
CLOCK_MONOTONIC bergerak monoton tetapi tidak memasukkan waktu ketika sistem berada dalam kondisi suspend. CLOCK_BOOTTIME juga monoton dan memasukkan waktu suspend. Karena itu, timer berbasis CLOCK_BOOTTIME dapat menghitung interval suspend yang tidak dihitung timer CLOCK_MONOTONIC.
CLOCK_REALTIME merepresentasikan wall-clock yang dapat diubah. Perubahan diskontinu pada clock ini dapat memindahkan deadline absolut relatif terhadap nilai wall-clock yang baru. Properti tersebut cocok untuk sebagian deadline berbasis kalender, tetapi berbeda dari pengukuran durasi.
Pemilihan clock merupakan bagian dari semantik timer. Readiness descriptor tidak menghapus perbedaan antara clock untuk waktu berlalu dan clock waktu sipil yang dapat diubah.
Timer real-time absolut dapat melaporkan diskontinuitas clock
Untuk timer absolut berbasis CLOCK_REALTIME atau CLOCK_REALTIME_ALARM, TFD_TIMER_CANCEL_ON_SET menandai timer agar dapat dibatalkan ketika real-time clock berubah secara diskontinu.
struct itimerspec spec = {
.it_value = deadline,
.it_interval = {0, 0},
};
int rc = timerfd_settime(
timer_fd,
TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
&spec,
NULL
);Setelah perubahan clock yang memenuhi kondisi tersebut, read() saat ini atau berikutnya gagal dengan ECANCELED. Hasil ini membedakan diskontinuitas clock dari ekspirasi biasa. Software yang memetakan deadline wall-clock ke event eksternal dapat menghitung ulang state tanpa menganggap deadline lama tercapai secara normal.
Perilaku pembatalan ini khusus untuk real-time clock yang memenuhi syarat dan penggunaan kedua flag secara bersamaan. Perilaku tersebut bukan properti umum semua timerfd.
Readiness dan accounting timer tetap dalam satu event loop
timerfd dapat didaftarkan bersama socket dan pipe dalam satu set epoll. Event loop menerima readiness descriptor, lalu mengonsumsi penghitung ekspirasi dengan read(). Jalur timer tersebut tidak memerlukan signal handler.
Hal ini tidak membuat delivery timer identik dengan I/O byte-stream. Descriptor merepresentasikan objek timer kernel, dan operasi read memiliki semantik khusus timer: penghitung ekspirasi 8 byte, blocking atau EAGAIN ketika tidak ada ekspirasi tertunda, serta ECANCELED opsional untuk diskontinuitas wall-clock tertentu.
Batas mekanismenya jelas: timerfd mengubah state ekspirasi timer menjadi readiness descriptor dan hasil read yang terhitung. Event multiplexing menangani notifikasi, sedangkan penghitung yang dikembalikan mempertahankan jumlah ekspirasi yang telah berlalu.