sleep() の背後にあるアルゴリズムは何ですか?

質問の「更新」は、最新の OS の仕組みについての誤解を示しています。

カーネルはタイム スライスを「許可」されていません。カーネルは、ユーザー プロセスにタイム スライスを提供するものです。 「タイマー」は、スリープ状態のプロセスを起動するようには設定されていません。現在実行中のプロセスを停止するように設定されています。

要するに、カーネルは、CPU 上に長時間置かれているプロセスを停止することによって、CPU 時間を公平に分配しようとします。簡単に説明すると、どのプロセスも 2 ミリ秒を超えて CPU を使用できないとします。したがって、カーネルはタイマーを 2 ミリ秒に設定し、プロセスを実行させます。タイマーが割り込みを発生させると、カーネルが制御を取得します。実行中のプロセスの現在の状態 (レジスタ、命令ポインターなど) を保存し、制御は戻りません。代わりに、CPU の割り当てを待機しているプロセスのリストから別のプロセスが選択され、中断されたプロセスはキューの後ろに移動します。

スリープ プロセスは単に そうではありません CPUを待っているもののキューで。代わりに、スリープ キューに格納されます。カーネルがタイマー割り込みを受け取るたびに、スリープ キューがチェックされ、時間になったプロセスは「CPU 待ち」キューに転送されます。

もちろん、これは大幅な単純化です。セキュリティ、公平性、バランス、優先順位付け、飢餓の防止を確保するには、非常に洗練されたアルゴリズムが必要であり、カーネル データに使用されるメモリ量を最小限に抑えてすべてを高速に実行します。


スリープ キューと呼ばれるカーネル データ構造があります。優先待ち行列です。プロセスがスリープ キューに追加されるたびに、最も早く起動されるプロセスの有効期限が計算され、タイマーが設定されます。その時点で、期限切れのジョブがキューから削除され、プロセスが実行を再開します。

(面白い豆知識:古い UNIX の実装では、fork() が呼び出されたプロセスのキューがありましたが、子プロセスは作成されていませんでした。もちろん、それは フォーク キュー<と呼ばれていました。 /em> .)

HTH!


おそらく、オペレーティング システムの主な仕事は、実際のハードウェアの複雑さをアプリケーション作成者から隠すことです。したがって、OS がどのように機能するかを説明すると、非常に複雑になり、非常に高速になるリスクがあります。したがって、実際のオペレーティング システムが対処する必要があるすべての「もしも」や「ええと」を扱うつもりはありません。プロセスとは何か、プロセスとは何か、ということを高い概念レベルで説明するだけです。スケジューラーは、タイマー キューがどのように機能するかを示します。うまくいけば、これが役に立ちます。

プロセスとは:

プロセスについて考えてみましょう - プロセスについてだけ話し、後でスレッドに行きましょう - 「オペレーティングシステムがスケジュールするもの」と考えてください。プロセスには ID があります (整数と考えてください)。その整数は、そのプロセスのすべてのコンテキストを含むテーブルへのインデックスと考えることができます。

コンテキスト ハードウェア情報 (レジスタ、メモリ管理ユニットの内容、その他のハードウェア状態) であり、マシンにロードされたときにプロセスを「実行」できるようにします。コンテキストには他にもコンポーネントがあります。開いているファイルのリスト、シグナル ハンドラの状態、そしてここで最も重要なのはプロセスが待機しているものです。 .

プロセスは多くの時間をスリープ (待機) に費やします

プロセスは待機に多くの時間を費やします。たとえば、ディスクの読み取りまたは書き込みを行うプロセスは、データが到着するか、ディスクに出力されたことを確認するために多くの時間を費やします。 OS 関係者は、「待機中」と「スリープ中」(および「ブロック済み」) という用語をある程度同じ意味で使用します。これらはすべて、プロセスが楽しい道を進む前に何かが起こるのを待っていることを意味します。 OS API の sleep() がたまたまスリープ プロセスの基礎となる OS メカニズムを使用していることは、混乱を招くだけです。

プロセスは、ネットワーク パケットの到着、ウィンドウ選択イベント、タイマーの期限切れなど、他のことを待機している可能性があります。

プロセスとスケジューリング

待機中のプロセスは実行不可能と呼ばれます .オペレーティング システムの実行キューには入りません。しかし、プロセスが待機しているイベントが発生すると、オペレーティング システムはプロセスを実行不可能な状態から実行可能な状態に移行させます。同時に、オペレーティング システムはプロセスを実行キューに入れますが、これは実際にはキューではありません。オペレーティング システムがそうすることを決定した場合、できます 走る。

スケジューリング:

オペレーティング システムは、定期的にどのプロセスを実行するかを決定します。オペレーティング システムがそのようにすることを決定するアルゴリズムは、多少驚くことではありませんが、スケジューリング アルゴリズムと呼ばれます。スケジューリング アルゴリズムは、非常に単純なもの (「全員が 10 ミリ秒実行し、次にキューの次の人が実行する」) から、はるかに複雑なもの (プロセスの優先度、実行頻度、実行時間の締め切り、プロセス間の依存関係、連鎖ロック、およびその他のあらゆる種類の複雑な主題)。

タイマー キュー パソコンにはタイマーが内蔵されています。これを実装する方法はたくさんありますが、古典的な方法は定期タイマーと呼ばれます .定期的なタイマーは一定の間隔で刻みます。今日のほとんどのオペレーティング システムでは、この速度は 1 秒あたり 100 回、100 Hz、10 ミリ秒ごとです。この値を以下の具体的なレートとして使用しますが、ほとんどのオペレーティング システムはさまざまなティックで構成できることを知っています。多くのオペレーティング システムはこのメカニズムを使用せず、はるかに優れたタイマー精度を提供できます。しかし、余談です。

ティックごとに、オペレーティング システムへの割り込みが発生します。

OS がこのタイマー割り込みを処理するとき、システム時間の概念をさらに 10 ミリ秒増やします。次に、タイマー キューを調べて、そのキューのどのイベントを処理する必要があるかを判断します。

タイマー キューは実際には 「対処する必要があるもの」のキュー。これをイベントと呼びます。このキューは有効期限の順に並べられ、最も早いイベントが最初になります。

「イベント」は、「プロセス X をウェイクアップする」、「ディスク I/O が動かなくなった可能性があるため、あちらでキックする」、「あちらのファイバーチャネル リンクでキープアライブ パケットを送信する」などのようなものです。オペレーティング システムが実行する必要があることは何でも。

このように並べられたキューがある場合、デキューの管理は簡単です。 OS は単純にキューの先頭を見て、イベントの「有効期限までの時間」をティックごとに 10 ミリ秒ずつ減らします。有効期限がゼロになると、OS はそのイベントをデキューし、必要な処理を行います。

スリープ中のプロセスの場合、プロセスを再び実行可能にするだけです。

シンプルですね。