CLOCK_REALTIMEとCLOCK_MONOTONICの違いは?


206

あなたは違い説明できたCLOCK_REALTIMECLOCK_MONOTONICによって返されたクロックclock_gettime()Linux上の?

外部ソースによって生成されたタイムスタンプと現在の時刻の間の経過時間を計算する必要がある場合、どちらが適切な選択ですか?

最後に、私は定期的に、システム時刻を調整するNTPデーモンを持っている場合はどのように行うのそれぞれとの相互作用これらの調整CLOCK_REALTIMECLOCK_MONOTONIC

回答:


238

CLOCK_REALTIME現在のウォールクロックの時刻に関するマシンの最良の推測を表します。以下のようイグナシオMarkRは言う、この手段CLOCK_REALTIMEシステム時刻クロックとして前後にジャンプすることができますは、NTPによる含め、変更されました。

CLOCK_MONOTONIC過去の任意の固定点からの絶対経過時間を表します。システムの時刻時計の変更による影響は受けません。

再起動を介さずに1台のマシンで観測された2つのイベント間の経過時間を計算する場合CLOCK_MONOTONICは、これが最適なオプションです。

Linuxでは、CLOCK_MONOTONICPOSIXの定義により、サスペンドに費やされた時間を測定しないことに注意してください。CLOCK_BOOTTIMEサスペンド中に実行を継続する単調クロックには、Linux固有を使用できます。


11
新しいカーネルでは、CLOCK_MONOTONIC_RAWが利用可能で、さらに優れていることに注意してください(NTP調整なし)。
ジョセフガービン

14
@JosephGarvinの値が「より良い」の場合、おそらく— CLOCK_MONOTONIC_RAWは、リアルタイムで数百万分の1(数百)の速度で実行される場合があり、その速度は、温度や電圧などの環境条件(または仮想マシン)。適切に機能しているマシンでは、NTPはこれらの要因をすべて軽減するために最善を尽くします。そのため、CLOCK_MONOTONICは実際の経過時間をより厳密に反映します
ホッブ

23
確かに、CLOCK_MONOTONIC_PARBOILEDは、周波数エラーを修正するNTPの取り組みの影響を受けたが、位相エラーを修正する取り組みの影響は受けなかったが、疑わしいゲインの場合は非常に複雑になる:)
hobbs

1
@hobbsが指摘する点が気に入っています。クロックドリフトの影響を受ける可能性のあるプログラムについて心配している場合はどうなりますか?だろうCLOCK_MONOTONICというシナリオで最良の選択でありますか?例:パトリオットミサイルシステム
sjagr

3
CLOCK_REALTIMEはうるう秒の影響を受けることにも言及することが重要だと思います。これは、うるう秒が挿入されるたびに二重のタイムスタンプ生成すること意味します。前回これが2012年6月30日に発生し、非常に多くのソフトウェアが問題に遭遇しました
user1202136 2014

38

Robert Loveの著書 『LINUX System Programming 2nd Edition』は、第11章363ページの冒頭で具体的に質問に対応しています。

単調な時間ソースの重要な側面は現在の値ではありませんが、時間ソースが厳密に線形に増加していることの保証であり、したがって、2つのサンプリング間の時間差を計算するのに役立ちます

そうは言っても、プロセスがOSの同じインスタンスで実行されていると彼は想定しているので、ドリフトを推定できるように定期的なキャリブレーションを実行することをお勧めします。


25

CLOCK_REALTIMENTPの影響を受け、前後に移動できます。CLOCK_MONOTONICそうではなく、ティックごとに1ティックずつ進みます。


15
CLOCK_MONOTONICは、NTPの時間調整(時間スルー)の影響を受けます。ただし、ジャンプしません。
derobert 2011

3
しかし、新しいカーネルにはCLOCK_MONOTONIC_RAWがあり、これは実際にはNTPの影響を受けません。
ジョセフ・ガービン、2012

1
「ティック」-Linux / amd64でティック/ティック/ CPU命令がどれくらいティックであるか、おおまかな考えはありますか?または、これに関するドキュメントはどこで入手できますか?
kevinarpe 2014

@kevinarpeわかりませんが、ティックはCPUサイクルの数ではなく、時間の一部として定義されると思います。多くの場合、1/100秒です。
ステファン

@Stéphane:私はきっと10msよりきついはずです。私はJavaのSystem.nanoTime()使用を考え、1000ns以下の時間CLOCK_MONOTONIC測定できると思います。たぶんあなたは時々ミリ秒に制限されているシステム時間について考えていますか?
kevinarpe

20

加えて、イグナシオの答えはCLOCK_REALTIME時折後方飛躍に前進上がる、とすることができます。CLOCK_MONOTONICどちらも行いません。前進し続けるだけです(ただし、再起動時にリセットされる可能性があります)。

堅牢なアプリは、CLOCK_REALTIMEときどき前方への跳躍を許容できる必要があります(そして、たぶん非常にまれに後方に跳躍する可能性がありますが、これはエッジケースに近いものです)。

ラップトップをサスペンドしたときに何が起こるか想像してみてください- CLOCK_REALTIME再開後にジャンプしますが、ジャンプCLOCK_MONOTONICしません。VMで試してください。


3
CLOCK_MONOTONICは、プログラムの開始時に0から始まります。プロセス間で使用するためのものではありません。
Benubird、2011

18
@Benubird:プログラムの起動時に0から開始されません。それCLOCK_PROCESS_CPUTIME_IDです。クイックテスト:$ perl -w -MTime::HiRes=clock_gettime,CLOCK_MONOTONIC -E 'say clock_gettime(CLOCK_MONOTONIC)'-> 706724.117565279。その数はLinuxのシステム稼働時間と一致しますが、標準では任意としています。
derobert 2011

4
余談ですCLOCK_MONOTONICが、サスペンド/レジュームで停止するLinuxの動作がPOSIXに準拠しているとは思いません。それは過去の定点からの時間であるはずですが、サスペンド/レジュームでクロックを停止すると壊れます。
カフェ

15

POSIX 7の引用

POSIX 7は、http//pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.htmlで両方を指定しています。

CLOCK_REALTIME

このクロックは、システムのリアルタイムを測定するクロックを表します。このクロックの場合、clock_gettime()によって返され、clock_settime()によって指定された値は、エポック以降の時間(秒およびナノ秒)を表します。

CLOCK_MONOTONIC (オプション機能):

このクロックの場合、clock_gettime()によって返される値は、過去の不特定の時点からの時間(秒およびナノ秒単位)を表します(たとえば、システムの起動時間やエポック)。このポイントは、システムの起動後は変わりません。CLOCK_MONOTONICクロックの値は、clock_settime()を介して設定できません。

clock_settime()重要なヒントを提供します:POSIXシステムはCLOCK_REALITMEそれと共に任意に変更できるので、継続的にも順方向にも流れないことに依存しないでください。NTPはを使用して実装clock_settime()でき、影響を与えるだけCLOCK_REALITMEです。

Linuxカーネルの実装はのためのエポックとして起動時間がかかるようだCLOCK_MONOTONICCLOCK_MONOTONICのための出発点


0

これをコメントとして追加する評価はありません。したがって、それは補完的な答えになります。

呼び出す頻度にもよりますが、VDSOのLinuxから提供されるのは「クロック」の一部clock_gettime()のみであることを覚えておく必要があります(つまり、1つのオーバーヘッドをすべて備えたシステムコールは必要ありません。これはLinuxが追加されたときにのみ悪化します。 Spectreのような攻撃から保護するための防御)。

一方でclock_gettime(CLOCK_MONOTONIC,...)clock_gettime(CLOCK_REALTIME,...)とは、gettimeofday()常に(VDSOによって加速)非常に高速であることを行っている、これはありません、例えばCLOCK_MONOTONIC_RAWまたは他のPOSIXクロックのいずれかに当てはまります。

これは、カーネルのバージョンとアーキテクチャによって変わる可能性があります。

ほとんどのプログラムはこれに注意を払う必要はありませんが、VDSOによって加速されたクロックにレイテンシのスパイクが発生する可能性があります。カーネルがクロックカウンターで共有メモリ領域を更新しているときに、クロックヒットが発生すると、待機する必要があります。終了するカーネル。

これが「証拠」です(ボットをkernel.orgから遠ざけるためのGitHub):https : //github.com/torvalds/linux/commit/2aae950b21e4bc789d1fc6668faf67e8748300b7


0

CLOCK_REALTIME :絶対時間(例:2020年1月7日)

CLOCK_MONOTONIC:相対時間(たとえば、現在から5秒、または10分前)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.