7

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

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

  • CLOCK_MONOTONIC - これが何なのか (そして SI 秒が何を意味するのか) はわかりませんが、この時計が逆方向にジャンプすることはなく、値が単調に増加することしかできないことは理解しています。

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

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

現在、BSD システムには 2 つのスリープ関数があります。sleep()nanosleep()。確かではありませんが、sleep() が nanosleep の上に実装されることを期待します。結局、nanosleep() を使用して sleep() を簡単にエミュレートし、構造体の timespec で秒数を設定するだけで、ナノ秒をゼロに保つことができます。 .

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

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

さまざまな情報源によると、スリープ (少なくとも nanosleep) は内部でクロックとして CLOCK_REALTIME を使用します。つまり、nanosleep() に 30 秒間スリープするように指示してから、システム クロックを将来の 1 時間に変更すると、スレッドはほぼ即座にウェイクアップします (将来の 1 時間は、ウェイクアップ時間 nanosleep( ) 計算)。これも全然オッケーです。しかし、私が 30 秒で目を覚ますと言った後、ユーザーが自分のシステム時計が 1 時間進んでいることに気づき、時計を 1 時間遅らせたらどうなるでしょうか? 次に、私のスレッドは 1 時間 30 秒間スリープしますか? それはかなり悪いでしょう。

4

2 に答える 2

4

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

このように、スリープ時間は、将来のある時点までスリープするのではなく、常に実際にスリープする時間になります。この理由は、ご想像のとおり、将来の時間を選択すると、そこにたどり着けない可能性がある (または予想外の時間でそこにたどり着く可能性がある) ためです。これは、プログラムでスリープを使用する目的と一致しています。カレンダーのような計算を行うためのものではありません。

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

于 2009-01-09T12:06:14.630 に答える
2

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

于 2009-01-09T12:22:15.550 に答える