ユーザーモードとカーネルモードの違いは何ですか?なぜ、どのようにしてどちらをアクティブにするのですか?また、それらの使用例は何ですか?
ユーザーモードとカーネルモードの違いは何ですか?なぜ、どのようにしてどちらをアクティブにするのですか?また、それらの使用例は何ですか?
回答:
カーネルモード
カーネルモードでは、実行中のコードは基盤となるハードウェアに完全かつ無制限にアクセスできます。任意の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つのアプリケーションが別のアプリケーションに属するデータを変更することはできません。各アプリケーションは分離して実行され、アプリケーションがクラッシュした場合、クラッシュはその1つのアプリケーションに限定されます。他のアプリケーションとオペレーティングシステムは、クラッシュの影響を受けません。
プライベートであることに加えて、ユーザーモードアプリケーションの仮想アドレス空間は制限されています。ユーザーモードで実行されているプロセッサは、オペレーティングシステム用に予約されている仮想アドレスにアクセスできません。ユーザーモードアプリケーションの仮想アドレススペースを制限することで、アプリケーションが重要なオペレーティングシステムデータを変更したり、損傷したりするのを防ぐことができます。
カーネルモードで実行されるすべてのコードは、単一の仮想アドレス空間を共有します。これは、カーネルモードドライバーが他のドライバーやオペレーティングシステム自体から分離されていないことを意味します。カーネルモードドライバーが誤った仮想アドレスに誤って書き込むと、オペレーティングシステムまたは別のドライバーに属するデータが危険にさらされる可能性があります。カーネルモードドライバーがクラッシュすると、オペレーティングシステム全体がクラッシュします。
あなたがWindowsユーザーであれば、このリンクを一度通過すると、さらに多くを得るでしょう。
CPUリングは最も明確な違いです
x86保護モードでは、CPUは常に4つのリングのいずれかにあります。Linuxカーネルは0と3のみを使用します。
これは、カーネル対ユーザーランドの最もハードで高速な定義です。
Linuxがリング1および2を使用しない理由:CPU特権リング:リング1および2が使用されないのはなぜですか?
現在のリングはどのように決定されますか?
現在のリングは、次の組み合わせで選択されます。
グローバル記述子テーブル:GDTエントリのメモリ内テーブル。各エントリにはPrivl
、リングをエンコードするフィールドがあります。
LGDT命令は、アドレスを現在の記述子テーブルに設定します。
セグメントは、GDTのエントリのインデックスを指すCS、DSなどを登録します。
たとえばCS = 0
、GDTの最初のエントリが実行中のコードに対して現在アクティブであることを意味します。
各リングは何ができますか?
CPUチップは、次のように物理的に構築されています。
リング0は何でもできます
ring 3は、いくつかの命令を実行して、いくつかのレジスタに書き込むことができません。
自分のリングを変更することはできません!そうでなければ、それ自体がリング0に設定され、リングは役に立たなくなります。
つまり、現在のリングを決定する現在のセグメント記述子を変更できません。
はページテーブルを変更できません:x86ページングはどのように機能しますか?
つまり、CR3レジスタを変更できず、ページング自体がページテーブルの変更を防ぎます。
これにより、セキュリティ/プログラミングの容易さのために、1つのプロセスが他のプロセスのメモリを参照できなくなります。
割り込みハンドラを登録できません。それらはメモリ位置への書き込みによって構成されますが、これもページングによって防止されます。
ハンドラーはリング0で実行され、セキュリティモデルに違反します。
つまり、LGDTおよびLIDT命令は使用できません。
in
およびのようなIO命令を実行できないout
ため、任意のハードウェアアクセスが可能です。
それ以外の場合、たとえば、プログラムがディスクから直接読み取ることができる場合、ファイルのアクセス許可は役に立ちません。
より正確にはMichael Petchに感謝します。実際には、OSがリング3でIO命令を許可することが可能です。これは、実際にはTask状態セグメントによって制御されます。
リング3がそれを最初から持っていなかった場合、リング3がそれを許可することは不可能です。
Linuxは常にそれを拒否します。参照:LinuxがTSS経由でハードウェアコンテキストスイッチを使用しないのはなぜですか?
プログラムとオペレーティングシステムはリング間でどのように移行しますか?
CPUがオンになると、リング0で初期プログラムの実行を開始します(まあ、それは良い概算です)。この初期プログラムはカーネルであると考えることができます(ただし、通常は、まだリング0にあるカーネルを呼び出すブートローダーです)。
ユーザランドのプロセスがカーネルは、ファイルへの書き込みのようにそれのために何かをしたいとき、それはそのような割り込み生成指示使用していますint 0x80
かsyscall
カーネルを知らせるために。x86-64 Linux syscall hello worldの例:
.data
hello_world:
.ascii "hello world\n"
hello_world_len = . - hello_world
.text
.global _start
_start:
/* write */
mov $1, %rax
mov $1, %rdi
mov $hello_world, %rsi
mov $hello_world_len, %rdx
syscall
/* exit */
mov $60, %rax
mov $0, %rdi
syscall
コンパイルして実行:
as -o hello_world.o hello_world.S
ld -o hello_world.out hello_world.o
./hello_world.out
これが発生すると、CPUはカーネルがブート時に登録した割り込みコールバックハンドラーを呼び出します。ハンドラを登録して使用する具体的なベアメタルの例を次に示します。
このハンドラーはリング0で実行され、カーネルがこのアクションを許可するかどうかを決定し、アクションを実行し、リング3でユーザーランドプログラムを再起動します。x86_64
ときにexec
システムコールが使用されている(または場合カーネルが開始されます/init
)、カーネルは、レジスタおよびメモリ準備し、新しいユーザーランドプロセスのをそれがエントリポイントにジャンプし、リング3にCPUを切り替えます
(ページングのため)禁止されたレジスタまたはメモリアドレスへの書き込みなど、プログラムがエッチなことを行おうとすると、CPUはリング0のカーネルコールバックハンドラも呼び出します。
しかし、ユーザーランドはいたずらだったので、今回はカーネルがプロセスを強制終了するか、シグナルで警告を出す可能性があります。
カーネルが起動すると、一定の周波数でハードウェアクロックがセットアップされ、定期的に割り込みが生成されます。
このハードウェアクロックは、リング0を実行する割り込みを生成し、ウェイクアップするユーザーランドプロセスをスケジュールできるようにします。
このようにして、プロセスがシステムコールを実行していない場合でも、スケジューリングが行われる可能性があります。
複数のリングを持つことの意味は何ですか?
カーネルとユーザーランドを分離する主な利点は2つあります。
それをいじるには?
リングを直接操作するのに適したベアメタルセットアップを作成しました。https://github.com/cirosantilli/x86-bare-metal-examples
残念ながら、ユーザーランドの例を作る忍耐力はありませんでしたが、ページングの設定まで行ったので、ユーザーランドは実現可能です。プルリクエストを見たいです。
または、Linuxカーネルモジュールはリング0で実行されるので、それらを使用して特権操作を試すことができます。たとえば、制御レジスターを読み取ります。プログラムから制御レジスターcr0、cr2、cr3にアクセスする方法は?セグメンテーション違反の取得
ここで便利なQEMU + Buildrootセットアップあなたのホストを殺すことなく、それを試しては。
カーネルモジュールの欠点は、他のkthreadが実行中であり、実験に干渉する可能性があることです。しかし理論的には、カーネルモジュールですべての割り込みハンドラーを引き継ぎ、システムを所有することができます。
負のリング
負のリングは実際にはIntelのマニュアルで参照されていませんが、実際にはリング0自体よりもさらに機能を備えたCPUモードが存在するため、「負のリング」の名前に適しています。
1つの例は、仮想化で使用されるハイパーバイザーモードです。
詳細については、以下を参照してください。
腕
ARMでは、リングは代わりに例外レベルと呼ばれますが、主な考え方は同じです。
ARMv8には4つの例外レベルがあり、一般に次のように使用されます。
EL0:ユーザーランド
EL1:カーネル(ARM用語では「スーパーバイザー」)。
以前は統一されたアセンブリとsvc
呼ばれていた命令(SuperVisor Call)を入力します。これは、Linuxシステムコールの作成に使用される命令です。Hello world ARMv8の例:swi
こんにちは。
.text
.global _start
_start:
/* write */
mov x0, 1
ldr x1, =msg
ldr x2, =len
mov x8, 64
svc 0
/* exit */
mov x0, 0
mov x8, 93
svc 0
msg:
.ascii "hello syscall v8\n"
len = . - msg
Ubuntu 16.04のQEMUでテストします。
sudo apt-get install qemu-user gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-as -o hello.o hello.S
arm-linux-gnueabihf-ld -o hello hello.o
qemu-arm hello
以下は、SVCハンドラーを登録してSVC呼び出しを行う具体的なベアメタルの例です。
hvc
命令(HyperVisor Call)で入力されました。
ハイパーバイザーはOSに対するものであり、ユーザーランドにとってOSとは何か。
たとえば、Xenを使用すると、LinuxやWindowsなどの複数のOSを同じシステムで同時に実行でき、Linuxがユーザーランドプログラムと同じように、OSを互いに分離してセキュリティとデバッグを容易にします。
ハイパーバイザーは、今日のクラウドインフラストラクチャの重要な部分です。ハイパーバイザーは、単一のハードウェア上で複数のサーバーを実行できるようにし、ハードウェアの使用率を常に100%に保ち、大幅なコスト削減を実現します。
たとえばAWSは、KVMへの移行が発表される2017年までXenを使用していました。
EL3:さらに別のレベル。TODOの例。
smc
指示で入力(セキュアモードコール)
ARMv8アーキテクチャリファレンスモデルDDI 0487C.a -章D1 - AArch64システムレベルプログラマモデル-図D1-1が美しく、これを示しています。
ARMの状況は、ARMv8.1 Virtualization Host Extensions(VHE)の登場により少し変わりました。この拡張機能により、EL2でカーネルを効率的に実行できます。
VHEは、KVMなどのLinuxカーネル内の仮想化ソリューションがXenを上回ったために作成されました(たとえば、上記のAWSのKVMへの移行を参照)。ほとんどのクライアントはLinux VMのみを必要とし、想像できるように、すべてが単一のVMであるからです。プロジェクトでは、KVMはXenよりもシンプルで、潜在的に効率的です。そのため、これらの場合、ホストLinuxカーネルがハイパーバイザーとして機能します。
ARMは、後知恵の恩恵により、特権レベルの命名規則がx86よりも優れていることに注意してください。負のレベルは必要ありません。0は最低、3は最高です。高いレベルは、低いレベルよりも頻繁に作成される傾向があります。
現在のELは、次のMRS
命令で照会できます。現在の実行モード/例外レベルは何ですか?
ARMでは、チップ領域を節約する機能を必要としない実装を可能にするために、すべての例外レベルが存在する必要はありません。ARMv8の「例外レベル」は次のように述べています。
実装には、すべての例外レベルが含まれていない場合があります。すべての実装にはEL0とEL1を含める必要があります。EL2とEL3はオプションです。
EL1に例のデフォルトのためのQEMUが、EL2とEL3は、コマンドラインオプションを有効にすることができます:A53パワーアップをエミュレートする際のqemu-システムaarch64入るEL1
Ubuntu 18.10でテストされたコードスニペット。
in
そしてout
リング3にご利用いただけますTSSは、すべてまたは特定のポートへの読み取り/書き込みアクセスを許可する現在のタスクにIO許可テーブルを指すことができます。
私は暗闇の中で突き刺すつもりだし、あなたはWindowsについて話していると思います。簡単に言えば、カーネルモードはハードウェアへの完全なアクセス権を持っていますが、ユーザーモードはそうではありません。たとえば、ほとんどのデバイスドライバーは、ハードウェアの詳細を制御する必要があるため、カーネルモードで書かれています。
このウィキブックも参照してください。
他の回答では、ユーザーモードとカーネルモードの違いが既に説明されています。詳細を知りたい場合は、Windows Internalsのコピーを入手してください。これは 、Mark RussinovichとDavid Solomonによって書かれた、さまざまなWindowsオペレーティングシステムのアーキテクチャと内部の詳細を説明した優れた本です。
何
基本的に、カーネルモードとユーザーモードの違いはOSに依存せず、ハードウェア設計により、一部の命令がカーネルモードでのみ実行されるように制限することによってのみ達成されます。メモリ保護のような他のすべての目的は、その制限によってのみ実行できます。
どうやって
これは、プロセッサがカーネルモードまたはユーザーモードで動作していることを意味します。アーキテクチャは、いくつかのメカニズムを使用して、カーネルモードに切り替えられるたびに、OSコードがフェッチされて実行されることを保証できます。
なぜ
このハードウェアインフラストラクチャがあれば、これらは一般的なOSで実現できます。