スリープ状態のスレッドに対するシステム時間の変更の影響は何ですか?

StackOverflow https://stackoverflow.com/questions/427808

  •  06-07-2019
  •  | 
  •  

質問

clock_gettime()をご覧くださいすべてのBSDで使用でき、実際にはPOSIX標準の一部として定義されている関数、少なくとも3種類のクロックのサポートがあることがわかります(多くのシステムはこれらのクロックより多くをサポートしていますが、実際にはPOSIX標準は存在し、他はすべてオプションです):

  • CLOCK_REALTIME -POSIXはこれが存在することを要求します。これが実時間時計です。

  • CLOCK_MONOTONIC -これが何であるか(およびSI秒が何を意味するか)わかりませんが、このクロックは決して後方にジャンプせず、値は単調にしか増加しないことを理解しています。

  • CLOCK_UPTIME -これがCLOCK_MONOTONICとどのように異なるかわかりません(アップタイムも逆方向にジャンプすることはありません)が、少なくとも、このクロックはカーネルの起動時にゼロから開始することがわかります(カーネルの起動時にCLOCK_MONOTONICが持つ初期値は定義されていません)

1秒間、他のクロックを無視しましょう。 CLOCK_REALTIMEは単調に上向きにカウントすることを保証されていませんよね?これは実際の「システム時間」です。システム時間は自由に変更できます。過去3か月または5年先に設定できます。システムがネット上のNTPサーバーを使用して時刻を同期するたびに、時刻が前後にジャンプする場合があります。

現在、BSDシステムには2つのスリープ関数があります。 sleep()および nanosleep()。よくわかりませんが、nanosleep()を使用してsleep()を簡単にエミュレートし、ナノ秒を0に保ちながらstruct timespecで秒数を設定するだけで、sleep()がnanosleepの上に実装されることを期待しています。

これらの関数は実際にウェイクアップ時間を計算することで機能し(現在の時刻を取得し、それに睡眠量を追加)、現在の時刻がであれば定期的にチェックすることを多くのソースで読みました。ウェイクアップ時刻よりも後である場合は、スレッドを再度ウェイクアップします。これが間隔でのみチェックされるという事実は、マニュアルページが現在のスリープが少なくともこの時間(信号によって中断された場合のみより短い時間)スリープすると言う理由ですが、より長くスリープする可能性があります(頻度によって異なります)システムは、ウェイクアップ時間をすでに過ぎているかどうか、およびスケジューラーがこのスレッドの再実行を許可するまでにかかる時間に応じてチェックします。

これは私にとって完全に正気です...しかし、常に私を悩ませた1つの質問があります:

さまざまなソースによると、スリープ(少なくともnanosleep)は内部的にクロックとしてCLOCK_REALTIMEを使用します。つまり、nanosleep()に30秒間スリープさせ、その後システムクロックを1時間に変更すると、スレッドはほぼすぐに起動します(1時間後は、起動時間nanosleep( )計算済み)。これもまったく問題ありません。 しかし 30秒後に目覚めた後、ユーザーがシステムクロックが1時間進んでいることを知り、クロックを1時間遅らせるとどうなりますか?その後、私のスレッドは1時間30秒間スリープしますか?それはかなり悪いでしょう。

役に立ちましたか?

解決

私が知る限り、スリープ機能は通常、デクリメントカウンタのように実装されます。 「10秒間寝る」と言います。これは、「1000スケジュールティックの間スリープ」に変換されます。スケジューラで、スケジューラがスリープ中のプロセスをチェックするたびに、残り時間が減ります。

この方法では、スリープ時間は、将来のある時間までスリープするのではなく、常にリアルタイムのスリープ時間になります。この理由は、あなたが疑ったように、将来の時間を選択した場合、そこに到達することはないかもしれません(または、予想外の時間で到達するかもしれません)。これは、プログラムでスリープを使用する場合と一致します。カレンダーのような計算を行うためのものではありません。

単純なテストを行い、プログラムを30秒間スリープさせ、nix" time"を使用することもできます。関数の実行時間を計るコマンドを実行し、開始後にシステムクロックを5分戻し、何が起こるかを確認します。

他のヒント

スレッドは、スリープの終点ではなく、スリープ期間に設定された内部カウンタをチェックします。使用される内部カウンターは、現在のシステム時間とは関係がないため、システム時間に変更が生じても影響を受けません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top