プリエンプティブでモノリシックなマルチタスキング オペレーティング システムでのコンテキスト切り替えには、システム サービス コール (スリープ、ミューテックスの取得、イベントの待機、I/O のブロック) によるスケジューラへの暗黙的な譲歩、または割り込みと実行中のタスクを交換することを決定するスケジューラ。
タスクがスケジューラによって交換されると、いくつかの重いことが起こります。
- すべてのアクションは、オペレーティング システム カーネルの一部として発生し、高いレベルの特権で実行されます。すべてのアクションがチェックされ (またはそうあるべきです)、スケジューラーによって下された決定がタスクに追加の権限を付与しないようにします (ローカルの root エクスプロイトを考えてください)。
- ユーザー モード プロセスのアドレス空間がスワップされます。これにより、メモリ マネージャーがページ テーブル レイアウトを操作し、新しいディレクトリ ベースをコントロール レジスタにロードします。
- これは、CPU キャッシュに保持されているデータが削除され、削除される可能性があることも意味します。タスクが頻繁に使用されるものにアクセスしたばかりで、コンテキストが切り替えられて「失われた」場合、これは最悪です(次のアクセスで[おそらく]メインメモリから再度フェッチする必要があります)
- カーネルにトラップする方法に応じて、カーネルの OUT をトラップする必要があります。たとえば、システム コールを実行すると、CPU は非常に正確な一連の手順を実行して、カーネルで実行されているコードに移行し、終了時にそれらの手順を巻き戻します。これらの手順は、プログラム内の別のモジュールへの関数呼び出しを行うよりも複雑であるため、より多くの時間がかかります。
私が理解しているように、グリーン スレッド タスクは非常に簡単です。ユーザー モード ディスパッチャーは、コルーチンが解放されるまで実行するようにコルーチンに指示します。上記のいくつかの違い:
- コルーチンのディスパッチはカーネル モードでは発生しません。実際、通常、グリーン スレッドのディスパッチには、オペレーティング システム サービスやブロッキング オペレーティング システム サービスが関与する必要はありません。したがって、これはすべて、コンテキストの切り替えやユーザー/カーネルの変換なしで実行できます。
- グリーン スレッドは、グリーン スレッド マネージャーによってプリエンプティブにスケジュールされることはなく、まったくプリエンプトされることさえありません。それらは協調的にスケジュールされます。これは良いことも悪いこともありますが、適切に作成されたルーチンがあれば、一般的には良いことです。各タスクは、必要なことを正確に実行してから、ディスパッチャにトラップしますが、コンテキスト スワップのオーバーヘッドはありません。
- 緑のスレッドはアドレス空間を共有しています (私の知る限り)。コンテキスト スイッチでは、アドレス空間のスワッピングは発生しません。スタックは (私の知る限り) スワップされますが、それらのスタックはディスパッチャによって管理され、スタックのスワップはレジスタへの単純な書き込みです。スタックのスワップも非特権操作です。
つまり、ユーザー モードでのコンテキスト スイッチには、いくつかのライブラリ呼び出しとスタック ポインター レジスタへの書き込みが含まれます。カーネル モードでのコンテキスト スイッチには、割り込み、ユーザー/カーネル遷移、およびアドレス空間の状態変化やキャッシュ フラッシュなどのシステム レベルの動作が含まれます。