最後のうるう秒に触発されて、POSIX 呼び出しを使用してタイミング (具体的にはインターバル タイマー) を調査してきました。
POSIX はタイマーを設定する方法をいくつか提供していますが、どれも問題があります:
sleep
そして、nanosleep
これらは信号によって中断された後に再起動するのが面倒であり、クロック スキューが発生します。追加の作業を行うことで、このスキューのすべてではありませんが一部を回避できますが、これらの関数はリアルタイム クロックを使用するため、落とし穴がないわけではありません。setitimer
またはより現代的なtimer_settime
もの — これらはインターバル タイマーとして設計されていますが、プロセスごとであるため、複数のアクティブなタイマーが必要な場合に問題になります。また、同期的に使用することもできませんが、それほど大したことではありません。clock_gettime
とclock_nanosleep
一緒に使用すると、正しい答えのように見えCLOCK_MONOTONIC
ます。clock_nanosleep
は絶対タイムアウトをサポートしているため、スリープしてタイムアウトをインクリメントし、繰り返すことができます。中断後の再起動も簡単です。残念ながら、これらの関数は Linux 固有のものである可能性もあります。Mac OS X や FreeBSD ではサポートされていません。pthread_cond_timedwait
は Mac で利用可能でありgettimeofday
、無愛想な回避策として使用できますが、Mac ではリアルタイム クロックでしか機能しないため、システム クロックが設定されている場合やうるう秒が発生した場合に誤動作する可能性があります。
不足している API はありますか? UNIX ライクなシステムで適切に動作するインターバル タイマーを作成する、適度に移植性のある方法はありますか?
行儀がよく、適度に移植性があるとは、次のことを意味します。
- クロック スキューが発生しにくい (もちろん、システム クロック自体のスキューを除く)
- 設定中のシステム クロックまたはうるう秒の発生に対する回復力
- 同じプロセスで複数のタイマーをサポートできる
- 少なくとも Linux、Mac OS X、および FreeBSD で利用可能
うるう秒に関するメモ(R..の回答に応じて):
POSIX の 1 日の長さは正確に 86,400 秒ですが、実際の 1 日がこれより長くなったり短くなったりすることはめったにありません。システムがこの不一致を解決する方法は実装によって定義されますが、うるう秒が前の秒と同じ UNIX タイムスタンプを共有するのは一般的です。参照:うるう秒とその処理方法.
Linux カーネルのうるう秒のバグは、時計を 1 秒戻した後にハウスキーピングを実行できなかったことが原因でした: https://lkml.org/lkml/2012/7/1/203。そのバグがなくても、時計は1 秒戻っていたでしょう。