web-dev-qa-db-ja.com

OSスケジューラはどのようにしてCPUの制御を取り戻しますか?

最近、CPUとオペレーティングシステムがどのように機能するかを学び始めましたが、マルチタスクを提供するオペレーティングシステムを備えたシングルCPUマシンの動作について少し混乱しています。

したがって、私のマシンに単一のCPUがあるとすると、これは、常に1つのプロセスしか実行できないことを意味します。

さて、私は、貴重なCPU時間へのアクセスを制御するためにオペレーティングシステムによって使用されるスケジューラもプロセスであるとしか想定できません。

したがって、このマシンでは、ユーザープロセスまたはスケジューリングシステムプロセスのいずれかが任意の時点で実行されますが、両方は実行されません。

だからここに質問があります:

スケジューラーが別のプロセスにCPUの制御を放棄したら、スケジューリング作業を行うために再度実行するために、CPU時間をどのようにして取り戻すことができますか?つまり、現在実行中の特定のプロセスがCPUを放棄(譲渡)しない場合、スケジューラ自体が再び実行され、適切なマルチタスクを確実に行うにはどうすればよいでしょうか。

これまでは、ユーザープロセスがシステムコールを介してI/O操作を要求した場合、システムコールでスケジューラに再度CPU時間を割り当てることができると考えていました。しかし、これがこのように機能するかどうかさえわかりません。

一方、問題のユーザープロセスが本質的にCPUにバインドされている場合、この観点から見ると、そのプロセスは永久に実行され、他のプロセスを許可せず、スケジューラーも再度実行することはできません。

タイムスライスされたスケジューリングを想定すると、実行されていないときに、スケジューラが別のプロセスの実行時間をどのようにスライスできるかわかりません。

この点について、ご意見やご参考をいただければ幸いです。

58
Edwin Dalorzo

OSは、Nミリ秒ごとに割り込みを生成するハードウェアタイマー( プログラマブルインターバルタイマー またはPIT)をセットアップします。その割り込みはカーネルに配信され、ユーザーコードが中断されます。

他のハードウェア割り込みと同様に機能します。たとえば、IOが完了すると、ディスクはカーネルに強制的に切り替えます。

43
usr

Googleは「中断」します。割り込みは、マルチスレッド化、Linux/Windowsなどのプリエンプティブカーネルの中心にあります。割り込みがないと、OSは何もしません。

調査/学習中は、最初の段落の「タイマー割り込み」、「ラウンドロビン」、「タイムスライス」、または「量子」についての説明は無視してください。実際には間違っていなくても、危険なほど誤解を招くおそれがあります。

OS用語では、割り込みには2つの種類があります。

  • ハードウェア割り込み–周辺機器からの実際のハードウェア信号によって開始される割り込み。これらは(ほぼ)いつでも発生し、実行中のスレッドからドライバーのコードに実行を切り替えます。

  • ソフトウェア割り込み–現在実行中のスレッドからのOS呼び出しによって開始された割り込み。

割り込みは、スケジューラーに準備/実行を待機していたスレッドを作成するように要求するか、待機/実行中のスレッドをプリエンプトさせる可能性があります。

最も重要な割り込みは、周辺機器ドライバーからのハードウェア割り込みです –ディスクからのIOを待機していたスレッドを準備する割り込み、NICカード、マウス、キーボード、USBなど。プリエンプティブカーネルを使用する最も重要な理由、およびロック、同期、シグナリングなどのすべての問題は、そのようなシステムには非常に優れたIOパフォーマンスハードウェア周辺機器があるためですそのハードウェアからのデータを待機していたスレッドを迅速に準備/実行できますレイテンシなしでスレッドが生成されないため、または定期的なタイマーの再スケジュールを待機しているため。

ペリフェラルからの応答に必要以上に時間がかかる場合に備えて、多くのシステムコールにはタイムアウトがあるため、定期的なスケジューリングの実行を引き起こすハードウェアタイマー割り込みは重要です。

マルチコアシステムでは、OSには他のコアでハードウェア割り込みを引き起こす可能性のあるプロセッサ間ドライバーがあり、OSがスレッドを複数のコアに割り込み/スケジュール/ディスパッチできるようにします。

深刻な過負荷状態のボックス、またはCPUを集中的に使用するアプリ(少数派)を実行しているボックスでは、OSは定期的なタイマー割り込みとその結果のスケジューリングを使用して、使用可能なコアの数よりも大きい準備ができたスレッドのセットを循環できます。そして、それぞれが使用可能なCPUリソースを共有できるようにします。ほとんどのシステムでは、これはまれにしか発生せず、あまり重要ではありません。

「クォンタム」、「残りのタイムスライスをあきらめる」、「ラウンドロビン」などを目にするたびに、私はうんざりしています...

10
Martin James

@usrの答えを補足するために、 Linuxカーネルについて から引用します。

スケジュール()関数

schedule()はスケジューラを実装します。その目的は、runqueueリストでプロセスを見つけ、それにCPUを割り当てることです。複数のカーネルルーチンによって、直接または遅延して呼び出されます。 [...]

遅延呼び出し

スケジューラは、現在の[プロセス]のneed_reschedフィールドを1に設定することで、遅延した方法で呼び出すこともできます。このフィールドの値のチェックは、ユーザーモードプロセスの実行を再開する前に常に行われるためです(「第4章の「割り込みと例外」から)、schedule()は近い将来確実に呼び出されます。

4
Tudor