ユーザーモードとカーネルモードの違いは何ですか?それらをアクティブ化する理由と方法は何ですか?また、それらのユースケースは何ですか?
カーネルモード
カーネルモードでは、実行中のコードは、基盤となるハードウェアに完全かつ無制限にアクセスできます。任意のCPU命令を実行し、任意のメモリアドレスを参照できます。カーネルモードは、通常、オペレーティングシステムの最も低レベルで最も信頼できる機能のために予約されています。カーネルモードでのクラッシュは壊滅的です。彼らはPC全体を停止します。
ユーザーモード
ユーザーモードでは、実行中のコードはハードウェアまたは参照メモリに直接アクセスできません。ユーザーモードで実行するコードは、ハードウェアまたはメモリにアクセスするためにシステムAPIに委任する必要があります。この種の分離によって提供される保護により、ユーザーモードでのクラッシュは常に回復可能です。コンピューターで実行されているコードのほとんどは、ユーザーモードで実行されます。
続きを読む
これらは、コンピューターが動作できる2つの異なるモードです。これに先立ち、コンピューターが大きな部屋のようになっていて、何かがクラッシュした場合、コンピューター全体が停止します。そのため、コンピューター設計者はそれを変更することにしました。最新のマイクロプロセッサは、少なくとも2つの異なる状態をハードウェアに実装しています。
ユーザーモード:
カーネルモード:
切り替えの方法。
ユーザーモードからカーネルモードへの切り替えは、CPUによって自動的に行われません。 CPUが割り込み(タイマー、キーボード、I/O)によって割り込まれています。割り込みが発生すると、CPUは現在実行中のプログラムの実行を停止し、カーネルモードに切り替え、割り込みハンドラーを実行します。このハンドラーは、CPUの状態を保存し、その操作を実行して、状態を復元し、ユーザーモードに戻ります。
http://en.wikibooks.org/wiki/Windows_Programming/User_Mode_vs_Kernel_Mode
http://tldp.org/HOWTO/KernelAnalysis-HOWTO-3.html
Windowsを実行しているコンピューターのプロセッサには、ユーザーモードとカーネルモードの2つの異なるモードがあります。プロセッサは、プロセッサで実行されているコードのタイプに応じて、2つのモードを切り替えます。アプリケーションはユーザーモードで実行され、コアオペレーティングシステムコンポーネントはカーネルモードで実行されます。多くのドライバーはカーネルモードで実行されますが、一部のドライバーはユーザーモードで実行されます。
ユーザーモードアプリケーションを起動すると、Windowsはアプリケーションのプロセスを作成します。このプロセスは、アプリケーションにプライベート仮想アドレス空間とプライベートハンドルテーブルを提供します。アプリケーションの仮想アドレス空間はプライベートであるため、あるアプリケーションは別のアプリケーションに属するデータを変更できません。各アプリケーションは独立して実行され、アプリケーションがクラッシュした場合、クラッシュはその1つのアプリケーションに限定されます。他のアプリケーションとオペレーティングシステムは、クラッシュの影響を受けません。
プライベートであることに加えて、ユーザーモードアプリケーションの仮想アドレス空間は制限されています。ユーザーモードで実行されているプロセッサは、オペレーティングシステム用に予約されている仮想アドレスにアクセスできません。ユーザーモードアプリケーションの仮想アドレス空間を制限することにより、アプリケーションが重要なオペレーティングシステムデータを変更したり、場合によっては損傷を与えたりすることを防ぎます。
カーネルモードで実行されるすべてのコードは、単一の仮想アドレススペースを共有します。つまり、カーネルモードドライバーは、他のドライバーやオペレーティングシステム自体から分離されていません。カーネルモードドライバーが誤って誤った仮想アドレスに書き込むと、オペレーティングシステムまたは別のドライバーに属するデータが危険にさらされる可能性があります。カーネルモードドライバーがクラッシュすると、オペレーティングシステム全体がクラッシュします。
あなたがWindowsユーザーである場合、一度このリンクを通過すると、より多くを得るでしょう。
暗闇の中で突き刺して、Windowsについて話していると思います。一言で言えば、カーネルモードはハードウェアに完全にアクセスできますが、ユーザーモードはそうではありません。たとえば、ほとんどではないにしても、多くのデバイスドライバーは、ハードウェアのより細かい詳細を制御する必要があるため、カーネルモードで記述されています。
このwikibook も参照してください。
他の回答では、ユーザーモードとカーネルモードの違いについて既に説明しました。本当に詳しく知りたい場合は、Mark Russinovichによって書かれた優れた本である Windows Internals のコピーを入手する必要があります。さまざまなWindowsオペレーティングシステムのアーキテクチャと内部の詳細を説明するDavid Solomon。
CPUリングは最も明確な区別です
X86保護モードでは、CPUは常に4つのリングのいずれかになります。 Linuxカーネルは0と3のみを使用します。
これは、カーネルとユーザーランドの最もハードで高速な定義です。
Linuxがリング1と2を使用しない理由: CPU特権リング:リング1と2が使用されない理由
現在のリングはどのように決定されますか?
現在のリングは、次の組み合わせで選択されます。
グローバル記述子テーブル:GDTエントリのメモリ内テーブル。各エントリには、リングをエンコードするフィールドPrivl
があります。
LGDT命令は、アドレスを現在の記述子テーブルに設定します。
セグメントはGDTのエントリのインデックスを指すCS、DSなどを登録します。
たとえば、CS = 0
は、GDTの最初のエントリが実行中のコードに対して現在アクティブであることを意味します。
各リングは何ができますか?
CPUチップは、次のように物理的に構築されています。
リング0は何でもできます
リング3は、複数の命令を実行して複数のレジスタに書き込むことはできません。
独自のリングを変更することはできません!そうしないと、リング自体をリング0に設定し、リングを使用できなくなります。
つまり、現在のリングを決定する現在の セグメント記述子 を変更することはできません。
ページテーブルを変更できません: x86ページングはどのように機能しますか?
つまり、CR3レジスタを変更できず、ページング自体がページテーブルの変更を妨げます。
これにより、1つのプロセスが他のプロセスのメモリをセキュリティ/プログラミングの容易さの理由で見ることができなくなります。
割り込みハンドラーを登録できません。それらはメモリ位置への書き込みによって設定されますが、これもページングによって防止されます。
ハンドラーはリング0で実行され、セキュリティモデルを破壊します。
つまり、LGDTおよびLIDT命令は使用できません。
IO in
やout
などの命令を実行できないため、任意のハードウェアアクセスが可能です。
そうしないと、たとえば、プログラムがディスクから直接読み取ることができる場合、ファイルのアクセス許可が役に立たなくなります。
正確には Michael Petch のおかげです。実際には、OSはリング3でIO命令を許可することができます。これは実際には タスク状態セグメント 。
不可能なことは、リング3がそもそも持っていなかった場合に、それを許可することです。
Linuxは常にそれを許可しません。参照: LinuxがTSS経由でハードウェアコンテキストスイッチを使用しないのはなぜですか?
プログラムとオペレーティングシステムはどのようにリング間を移行しますか?
cPUがオンになると、リング0で初期プログラムの実行が開始されます(それでもいいですが、これはおおよその目安です)。この初期プログラムはカーネルであると考えることができます(ただし、通常はブートローダーであり、リング0のままカーネルを呼び出します)。
ユーザーランドプロセスがカーネルにファイルへの書き込みのような何かをさせたい場合、int 0x80
などの割り込みを生成する命令を使用してカーネルに信号を送ります。
これが発生すると、CPUは、起動時にカーネルが登録したコールバックハンドラーを呼び出して割り込みます。
このハンドラーはリング0で実行され、カーネルがこのアクションを許可し、アクションを実行し、リング3のユーザーランドプログラムを再起動するかどうかを決定します。
exec
システムコールが使用される場合(またはカーネル が/init
を開始する場合)、カーネル はレジスタを準備し、新しいユーザーランドプロセスのメモリ 、エントリポイントにジャンプし、CPUをリング3に切り替えます
プログラムが(ページングのため)禁止されたレジスタまたはメモリアドレスへの書き込みのようないたずらをしようとすると、CPUはリング0でカーネルコールバックハンドラーも呼び出します。
しかし、ユーザーランドはいたずらだったので、カーネルは今回プロセスを強制終了するか、シグナルで警告を出すかもしれません。
カーネルが起動すると、一定の周波数でハードウェアクロックが設定され、定期的に割り込みが生成されます。
このハードウェアクロックは、リング0を実行する割り込みを生成し、起動するユーザーランドプロセスをスケジュールできるようにします。
このように、プロセスがシステムコールを行っていない場合でも、スケジューリングを行うことができます。
複数のリングを持つポイントは何ですか?
カーネルとユーザーランドを分離することには、2つの大きな利点があります。
それをいじる方法は?
リングを直接操作するのに適した方法であるはずのベアメタル設定を作成しました: https://github.com/cirosantilli/x86-bare-metal-examples
残念ながらユーザーランドの例を作成する忍耐はありませんでしたが、ページングのセットアップまで行ったので、ユーザーランドを実現できるはずです。プルリクエストをご覧ください。
または、Linuxカーネルモジュールはリング0で実行されるため、それらを使用して特権操作を試すことができます。制御レジスタを読み取ります: プログラムから制御レジスタcr0、cr2、cr3にアクセスするには?セグメンテーション違反の取得
ホストを殺さずに試してみるのに便利な QEMU + Buildroot setup があります。
カーネルモジュールの欠点は、他のkthreadが実行されており、実験に干渉する可能性があることです。しかし、理論的には、カーネルモジュールですべての割り込みハンドラを引き継いでシステムを所有することができます。これは実際には興味深いプロジェクトです。
負のリング
ネガティブリングは実際にはIntelマニュアルでは参照されていませんが、リング0自体よりもさらに機能があるCPUモードが実際に存在するため、「ネガティブリング」の名前に適しています。
1つの例は、仮想化で使用されるハイパーバイザーモードです。
詳細については、次を参照してください: https://security.stackexchange.com/questions/129098/what-is-protection-ring-1
ARM
ARMでは、リングは代わりに例外レベルと呼ばれますが、主な考え方は同じです。
ARMv8には4つの例外レベルがあり、一般的に次のように使用されます。
EL0:ユーザーランド
EL1:カーネル
EL2: hypervisors 、たとえば Xen 。
ハイパーバイザーはOSに対するものであり、OSはユーザーランドに対するものです。
たとえば、Xenを使用すると、LinuxやWindowsなどの複数のOSを同じシステム上で同時に実行でき、Linuxがユーザーランドプログラムで実行するのと同じように、セキュリティとデバッグを容易にするためにOSを互いに分離します。
ハイパーバイザーは、今日のクラウドインフラストラクチャの重要な部分です。複数のサーバーを単一のハードウェアで実行できるため、ハードウェアの使用率を常に100%近くに保ち、多くのお金を節約できます。
たとえば、AWSは、2017年まで がKVMに移行してニュースを作成するまでXenを使用していました 。
EL3:さらに別のレベル。 TODOの例。
ARMv8アーキテクチャリファレンスモデルDDI 0487C.a -第D1章-AArch64システムレベルプログラマモデル-図D1-1はこれを美しく示しています。
おそらく後知恵の恩恵によるARMの特権レベルの命名規則が、負のレベルを必要とせずにx86よりも優れていることに注意してください。0は下位、3は最高です。高いレベルは、低いレベルよりも頻繁に作成される傾向があります。
現在のELはMRS
命令でクエリできます: 現在の実行モード/例外レベルなどは何ですか?
ARMでは、チップ領域を節約する機能を必要としない実装を可能にするために、すべての例外レベルが存在する必要はありません。 ARMv8の「例外レベル」には次のように記載されています。
実装には、すべての例外レベルが含まれない場合があります。すべての実装には、EL0とEL1を含める必要があります。 EL2とEL3はオプションです。
たとえば、QEMUはデフォルトでEL1ですが、EL2とEL3はコマンドラインオプションで有効にできます: qemu-system-aarch64 a53 power up
何
基本的に、カーネルモードとユーザーモードの違いはOSに依存せず、ハードウェア設計によってカーネルモードでのみ実行されるように一部の命令を制限することによってのみ達成されます。メモリ保護などの他のすべての目的は、その制限によってのみ実行できます。
方法
つまり、プロセッサはカーネルモードまたはユーザーモードのいずれかで動作します。アーキテクチャは、いくつかのメカニズムを使用して、カーネルモードに切り替えられるたびにOSコードがフェッチされて実行されることを保証できます。
理由
このハードウェアインフラストラクチャがあれば、一般的なOSでこれらを実現できます。