多くのオペレーティングシステムのリファレンスでは、協調的な(プリエンプティブとは対照的な)マルチタスクでは、プロセスがCPUを明示的に自発的に中断するまで保持します。実行中のプロセスがすぐに満たされないI / O要求を実行する(たとえば、まだ利用できないキーストロークを要求する)場合、スケジューラはそれを中断しますか、それとも要求が処理されるまでCPUを本当に保持しますか?
[「I / Oのブロック」を「すぐに満たすことができないI / O要求を実行する」に置き換えるように編集しました。]
多くのオペレーティングシステムのリファレンスでは、協調的な(プリエンプティブとは対照的な)マルチタスクでは、プロセスがCPUを明示的に自発的に中断するまで保持します。実行中のプロセスがすぐに満たされないI / O要求を実行する(たとえば、まだ利用できないキーストロークを要求する)場合、スケジューラはそれを中断しますか、それとも要求が処理されるまでCPUを本当に保持しますか?
[「I / Oのブロック」を「すぐに満たすことができないI / O要求を実行する」に置き換えるように編集しました。]
回答:
真に「協力的な」設定で、ハードウェア保護がなければ、プロセスは確実にI / Oをブロックし、I / Oが完了するまで(またはまったく制御を放棄しないまで)制御を放棄できませんでした。たとえば、Windows 3.1はこの方法でした。1人のユーザープロセスがコンピューター全体を引き継ぎ、他の何かが実行されないようにしたい場合、それは可能です。
ただし、マルチタスクを使用するシステムでは、システムAPI I / Oコマンドが呼び出されたときに、プロセッサの制御を放棄することが期待されます。そのため、実行中のプロセスがI / Oでブロックする場合、プロセスが通常のシステムAPIを使用すると仮定すると、I / Oが完了するまで他のプロセスの実行が許可され、最終的にI / Oが完了すると元のプロセスが再開されます。言い換えれば、ブロッキングI / O関数を呼び出すことは、協調システム上のプロセスが自発的に中断できる1つの方法です。
実行中のプロセスがI / Oでブロックする場合
IOでのブロックは、プロセスを一時停止するのとほとんど同じです。Linuxカーネルのコンテキストでは、などのIOシステムコールを実行read()
すると、sysenter
または割り込みハンドラーがトリガーされ、そのIOを監視し、do_sys_read()
最終的に呼び出します。ここで、現在の要求がすぐに満たされない場合、関数はsched()
別のプロセスを実行する可能性のある呼び出しを行います。
協同システムのコンテキストでは、何らかのIO理由でシステムコールを行ったときに、要求を満たせない場合、カーネルが別のタスクを選択して実行することを期待しています。このドキュメントでは、いくつかの背景を説明します。基本的に、IOで待機した場合、そのIOを待機していると永遠にハングアップする可能性があります。協調スケジューリングのアイデアはsched()
、CPUを集中的に使用するタスクを実行する場合、頻繁に呼び出すか、同等のCPUを放棄するという方法です。
カーネルモードの考慮事項はさらに興味深いものになります。特定の組み込みプラットフォームなど、使用可能なアーキテクチャでは、ハードウェアまたはソフトウェアの割り込みに応答して割り込みハンドラーが呼び出されます。通常、実装上、割り込み処理を無効にする ことは可能ですが、これには欠点もあります。
協調スケジューリング(できればcooperative multitasking
)モデルでは、オペレーティングシステムがプロセスの実行時間を制御できないという意味で、スケジューラの概念はありません。
正しくプログラムされたアプリケーションは、I / O上のCPUを自発的に放棄します。ただし、不適切に作成されたアプリケーションは、I / Oを待機し続けるだけで、他のプロセスをブロックする可能性があります。
PS:このアプローチは、後からほとんどのOSによって(外部スケジューラーを備えた)プリエンプティブスケジューリングを支持してgivenめられ、現在では、さまざまなOSで使用されるあらゆる種類のさまざまなスケジューリングアルゴリズムがあります。
編集:私の答えは、元の形式(数年前:P)で説明されているスケジューリングに基づいていました。ジルがコメントしたように、一部のシステムはまだ協調スケジューリングを使用しています。そして、スケジューラーがあります。これらのシステムが純粋で元の形式でCOSを使用しているかどうかはわかりません。
協調マルチタスクは、実行中のコンテキストが明示的にスケジューラに制御を放棄する必要があることを意味し、必要に応じてコンテキスト切り替えの発生を防ぐことができます。
ほとんどの実装は、プロセッサ割り当ての公平性を高めるために、すぐに返らないシステムコールに対してコンテキスト切り替えを明示的に実行します。
通常、失敗したプロセス(またはシステムの残りの部分に対するサービスの意図的な拒否)のみが頻繁なタスク切り替えを防ぐことができます。
Gillesによって説明されているように、プリエンプションはシステムのアーキテクチャの制限であり、アクティブなタスクと強制的なコンテキストスイッチの時間的な中断を防ぎます。