1秒ごとに実行したい処理があるのに、別の仕事で3秒以上手が離せなかった。次にタイマーを確認したとき、何回分の期限が過ぎていたかを知りたい場合があります。Linuxのtimerfdは、タイマーをファイルディスクリプターとして待ち合わせ、読み取りで期限到来の回数を受け取る仕組みです。ただし、その回数は仕事が実行された回数ではありません。
簡単にまとめると?
- 周期タイマーのtimerfdを読むと、前回の成功した読み取り、または設定変更以降に期限が来た回数を受け取ります。
- 1秒周期を3.4秒で初めて読んで値3を得ても、仕事を3回実行した証明にはなりません。
- 遅れた分を全部処理するか、まとめて最新状態へ追いつくかは、用途に応じてアプリケーション側で決めます。
タイマーを、ほかの入出力と一緒に待つ
timerfd_createでタイマーを作ると、ファイルディスクリプターが返ります。これはソケットなどと同じく、pollやepollの待機対象にできます。通信の到着とタイマーの期限を一つのイベントループで扱えるため、時間待ちのためだけに別の処理経路を用意せずに済みます。
期限を決めるのはtimerfd_settimeです。最初にいつ期限が来るかをit_valueに、繰り返しの間隔をit_intervalに指定します。最初を1秒後、間隔を1秒にすれば、その後も1秒ごとの期限を設定できます。it_intervalが0なら一度だけのタイマーです。一方、it_valueを0にするとタイマーを停止します。「0秒後にすぐ発火させる」という指定ではありません。
期限が来れば読み取り可能になりますが、読み取り可能であることと、その場でアプリケーションがCPUを使えることは別です。ほかの処理が長引く場合や、スケジューラーが別の仕事を動かしている場合には、タイマーを読む時刻が遅れます。timerfdは、その遅れをなくす仕組みではありません。
3.4秒で読んだ値3は、過ぎた期限を数えている
説明のため、時刻0に設定し、最初の期限が1秒、以後も1秒間隔になる理想的なタイマーを考えます。途中で読み取りも再設定もしなければ、3.4秒の時点では1秒、2秒、3秒の三つの期限が過ぎています。このとき読む値は3です。
この読み取りが成功した後、4.2秒にもう一度読めば、その間に新たに過ぎた4秒の期限を数え、値1を受け取ります。最初からの合計4ではありません。読み取りは、前回の成功した読み取り、またはtimerfd_settimeによる設定変更からの期限到来回数を受け取ります。

readの戻り値と、読み取った整数にも違いがあります。成功したreadは8バイトを読み取ったことを戻り値8で表し、その8バイトの符号なし64ビット整数に期限到来回数が入ります。上の最初の例では、戻り値は8、受け取った整数は3です。
期限がまだ来ていなければ、通常の読み取りは待機します。TFD_NONBLOCKで作った非ブロッキングのtimerfdなら、待たずにEAGAINになります。これは「仕事が終わった」という知らせでも、読み出せる値0を受け取ったという意味でもありません。通常の読み取りに必要な8バイトより小さいバッファを渡すと、EINVALになります。
遅れた三回分を、どう扱うか
値3を読んだ後の方針には、少なくとも二つの選択肢があります。一つは、期限一回ごとに対応する処理を三回進める方法です。一定刻みのシミュレーションなど、各ステップに意味がある場合には候補になります。ただし、一回の処理に長い時間がかかる状況では、追いつくための処理中にも次の期限が来ます。回数だけを見て無制限に追いかけると、遅れが広がる可能性があります。
もう一つは、複数の期限をまとめ、最新の状態を一度だけ更新する方法です。画面に現在時刻を表示するなら、見逃した三つの古い表示を順に描くより、現在の表示を作るほうが目的に合うことがあります。この場合、受け取った期限到来回数3と、実際の更新回数1は意図して異なります。
センサー記録では、過去の期限が三つ来たことが分かっても、その三時点の測定値を後から取り出せるとは限りません。測定自体をしていなければ、timerfdの回数は失われたデータを復元しません。期限の遅れを記録する指標と、収集できたデータ件数を分けて管理する必要があります。
周期の基準と、仕事を動かす時刻を分ける
処理が終わってから毎回「1秒待つ」方法では、処理にかかった時間も次の開始までの間隔へ足されます。最初の期限と周期を設定したtimerfdでは、周期の期限を継続させたまま、読み取りが遅れた回数を受け取れます。ただし、その結果として仕事が正確に1秒間隔で実行されるわけではありません。期限の列と実行の列は別です。
初回の期限は、通常は設定時の時計の値からの相対時間です。TFD_TIMER_ABSTIMEを指定すると、選んだ時計上の絶対値として扱います。CLOCK_MONOTONICを選んだ場合、その絶対値はカレンダーの日付や時刻ではありません。起点を固定して次の期限を設計したい場合にも、どの時計の値を使っているかをそろえる必要があります。
CLOCK_MONOTONICはシステムのサスペンド中の時間を数えません。サスペンドを含む経過時間で期限を考えるならCLOCK_BOOTTIMEが候補になります。ただし、サスペンド中の時間を数えることと、眠っているシステムを起こすことも別です。後者にはALARM系の時計と、その利用に必要な権限という別の条件があります。
timerfdを選ぶときは、ほかの入出力と一緒に待ちたいか、遅れた期限を数える必要があるか、その回数をどう処理へ結びつけるかを確認すると判断しやすくなります。期限到来、読み取り、仕事の開始、仕事の完了を分けて記録すれば、どこで遅れが生じたかも追いやすくなります。
出典
- Linux man-pages 6.19: timerfd_create(2) — timerfd_settime、timerfd_gettime、read、時計とフラグの仕様。2026年10月22日確認。
図と時刻列は仕様を説明するための独自作成です。実際のLinux呼出し、負荷時の遅延、リアルタイム性能を測定した結果ではありません。
