Galvinの著書「Operating Systems and Concepts」で次の内容を読んだ。
モードビットと呼ばれるビットがコンピュータハードウェアに追加され、現在のモード(カーネル(0)またはユーザー(1))を表します。区別することができます。
ここでマルチプロセッサシステムの場合、プロセスがシステムコールを実行し、モードビットを1から0に変更すると仮定します。
これはマルチプロセッサシステムなので、ユーザーモードで他のプロセスを並列に実行できますが、モードビットが0に設定されていることはカーネルモードで不一致が発生することを意味します。
それでは、レジスタの数(モードビットを格納するために必要です)はプロセッサの数によって異なりますか?
答え1
あなたの本は仕事を過度に単純化しました。実際には、CPUがモードをどのように設定するかによって異なり、「ビット」である必要はなく、2つのモードしか必要ありません。
この質問では、Linux、Intel x86、およびマルチコアを想定しています。
マルチタスクは、Linux上でソフトウェアベースのコンテキスト切り替えによって達成されます。コンテキスト切り替えは、単にプロセッサが実行している操作(コアまたはCPU)を停止し、その状態をRAMに保存してから別のコンテキストに置き換えます。
x86は、プロセスレベルの実行が発生する前に各プロセッサに設定できるガードリングを実装しています。 Linuxカーネルは、メモリ空間で実行を開始する前にプロセスをRing 3(無許可)に設定してこの問題を処理します。前述のコンテキストスイッチの実装により、カーネルは特定のスレッド(通常はコアあたり2つのスレッド、Intel)で実行されるプロセスの概念を維持します。なぜなら、そのプログラムコードが実行されるたびに、カーネルは常にリングを3に設定するからです。プロセッサは毎秒数回コンテキスト切り替えを実行するため、多くのプロセスが同じコアで実行されます。 1つ以上のコアを使用して、本質的に同じ方法でこれを実行できます。
x86 Linuxでは、スレッドがリング3からリング0(ハイパーバイザー)に切り替えたい場合は、ソフトウェア割り込みを介してのみ切り替えることができます。 Ring 1とRing 2では特別なガイドラインも利用できますが、Linuxではこれを実装していません。 Linuxはソフトウェア割り込みハンドラを制御するため、スレッドがリング0にある場合でも、「カーネルスペース」、つまり同じスレッドでもカーネルの一部であるコードのみを実行できるようになります。ユーザー空間コードを実行します。オペレーティングシステムではこれが実際に行われる作業なので、システムコールと呼ばれます。これを「プロセス」がカーネルモードに切り替えてから戻ってくると思うか、ユーザースペースに戻すまでカーネルスペースコードのみが実行されるため、プロセスが実際に中断されるかどうかはユーザー次第です。
x86では、ハイリングのリングがローリングに切り替えることができるため、割り込みハンドラが完了した後に3に戻すことができます。これはすべてのシステムコールで発生するため、ハードウェアの観点から見ると、すべてのシステムコールはシステム上で何でも可能です。プログラムのすべてのコマンドを逆順に実行し、必要に応じてメモリからすべてのコードを削除できます。あるいは、リング 0 に切り替えてプログラムの先頭から実行を開始することもできます。ご覧のとおり、これらの例では、ハードウェアに「カーネル/ユーザー」モードの概念がないため、「カーネル/ユーザー」モードの概念を破ります。ただし、Linuxでは常にカーネル空間への呼び出しとユーザー空間への戻りとして実装されます(実際にはx86ではメモリはリング0で保護されていません)。
したがって、カーネル/ユーザーモードの切り替えは、スレッドガードリングを超えていますが、カーネルスペースでのみ実行してからユーザースペースに戻るように実装されているソフトウェア割り込みハンドラ、特にコマンドユーザースペースプロセスを実行することによって達成されます。システムコールですが、リング3に戻った後にのみ可能です。