linuxユーザーステータスとカーネルステータス切り替えの理解


linuxユーザーステータスとカーネルステータス切り替えの理解
 
LinuxはRing 3レベルの実行ユーザ状態を使用し,Ring 0はカーネル状態とし,Ring 1とRing 2は使用しなかった.Ring 3状態では、コードとデータを含むRing 0のアドレス空間にアクセスできません.Linuxプロセスの4 GBアドレス空間、3 G-4 G部分はみんな共有して、カーネル状態のアドレス空間で、ここはカーネル全体のコードとすべてのカーネルモジュールに保管して、カーネルが維持したデータです.ユーザは、作成されたプロセスがユーザ状態で実行されるプログラムを実行します.ファイル操作、ネットワークデータ送信などの操作を実行するには、write、sendなどのシステム呼び出しを使用する必要があります.これらのシステム呼び出しはカーネルのコードを呼び出して操作を完了します.この場合、Ring 0に切り替える必要があります.その後、3 GB-4 GBのカーネルアドレス空間に入り、これらのコード完了操作を実行し、完了後、Ring 3に切り替え、ユーザー状態に戻る.これにより,ユーザ状態のプログラムはカーネルアドレス空間を勝手に操作することができず,一定のセキュリティ保護作用を有する.保護モードは、メモリ・ページ・テーブルの操作などのメカニズムによって、プロセス間のアドレス空間が互いに衝突しないことを保証し、1つのプロセスの操作が別のプロセスのアドレス空間のデータを変更しないことを保証します.カーネル状態では、CPUは任意の命令を実行することができ、ユーザ状態では、CPUは非特権命令しか実行できない.CPUがカーネル状態にある場合、任意にユーザ状態に入ることができる.一方,CPUがユーザ状態にある場合,割り込みによりカーネル状態に入るしかない.一般的なプログラムは、最初はユーザ状態で実行する、プログラムがシステムリソースを使用する必要がある場合は、ソフト割り込みを呼び出してカーネル状態に入る必要がある.
 
1.ユーザ状態とカーネル状態の概念の違い
いったい何がユーザー状態なのか、何がカーネル状態なのか、この2つの基本概念は以前からよく理解されていなかったが、根本的な原因は個人的には、ほとんどの場合、私たちがプログラムを書くときに注目している重点と着目の角度が実現した機能とコードの論理性に置かれているため、まず1つの例を見てみよう.
1)例
void testfork(){
  if(0 = = fork()){
    printf(“create new process success!
”); } printf(“testfork ok
”); }

このコードは簡単で、機能の観点から見ると、実際にfork()を実行し、新しいプロセスを生成し、論理的な観点から、fork()が0を返すと関連文を印刷し、関数が最後にtestfork()関数を完全に実行することを示す文を印刷すると判断します.コードの実行ロジックと機能的にはこのように簡単で、全部で4行のコードで、上から次の1つの文が実行されているだけで、ユーザー状態とプロセス状態を体現する概念がどこにあるか全く見えません.
前述の2つが静的観測の観点であれば、このコードは、CPUが実行する命令に変換された後に実行をロードするプロセスであり、このプログラムが動的に実行される命令シーケンスである動的観点から見ることもできる.どのコードがロードされているのか、どのようにロードされているのかはオペレーティングシステムと密接に関連しています.
 
2)特権級
Unix/Linuxシステムに詳しい人は知っていますが、forkの仕事は実際にシステム呼び出しで対応する機能を完成し、具体的な仕事はsys_forkは実施を担当する.実はUnixかLinuxかにかかわらず、どのオペレーティングシステムにとっても、新しいプロセスを作成することはコア機能に属しています.それは、物理メモリの割り当て、親プロセスから関連情報のコピー、ページディレクトリのページ表のコピーなど、システムの物理リソースを消費するため、どのプログラムでも簡単にはできません.そこで、特権レベルの概念を自然に引き出し、明らかに、最も重要な権力は高特権レベルのプログラムによって実行されなければならない.そうすれば、集中管理を行い、限られたリソースのアクセスと使用の衝突を減らすことができる.
特権レベルは明らかに非常に有効な管理とプログラムの実行を制御する手段であるため、ハードウェア上で特権レベルに対して多くのサポートを行い、Intel x 86アーキテクチャのCPUにとっては全部で0~3 4つの特権レベルがあり、0レベルが最も高く、3レベルが最も低く、ハードウェア上では各命令を実行する際に指令が持つ特権レベルに対して相応の検査を行い、関連する概念はCPL、DPLとRPLがあり、ここではあまり述べない.ハードウェアはすでに特権レベルの使用に関するメカニズムを提供しており、ソフトウェアは自然によく利用される問題であり、これはオペレーティングシステムがしなければならないことであり、Unix/Linuxにとって、0級特権レベルと3級特権レベルしか使用されていない.すなわちUnix/Linuxシステムでは、0レベルの特権レベルで動作する命令はCPUが提供できる最高権力を有し、3レベルの特権レベルで動作する命令はCPUが提供する最低または最も基本的な権力を有する.
 
3)ユーザー状態とカーネル状態
今、私たちは特権レベルのスケジューリングからユーザー状態とカーネル状態を理解するのが理解しやすい.プログラムが3級の特権レベルで実行されている場合、ユーザー状態と呼ぶことができる.これは最低の特権レベルであり、普通のユーザープロセスが実行する特権レベルであり、大部分のユーザーが直接直面しているプログラムはユーザー状態で実行されているからだ.逆に,プログラムが0レベルの特権レベルで実行される場合,カーネル状態で実行されると呼ぶことができる.
ユーザ状態とカーネル状態で動作するプログラムには多くの違いがあるが,最も重要な違いは特権レベルの違い,すなわち権力の違いである.ユーザ状態で実行されるプログラムは、オペレーティングシステムのカーネルデータ構造やプログラムに直接アクセスできません.たとえば、上記の例のtestfork()ではsys_を直接呼び出すことはできません.fork()は、前者がユーザ状態で動作するため、ユーザ状態プログラムに属し、sys_fork()はカーネル状態で動作し、カーネル状態プログラムに属する.
システムでプログラムを実行する場合、ほとんどの時間はユーザー状態で実行され、オペレーティングシステムが権限と能力のない作業を完了するのに役立つ必要がある場合、testfork()などのカーネル状態に切り替えられます.最初はユーザー状態プロセスで実行され、fork()を呼び出すとsys_が最終的にトリガーされます.fork()の実行時にカーネル状態に切り替わります.
 
2.ユーザ状態とカーネル状態の変換
1)ユーザ状態からカーネル状態への切り替えの3つの方式
a.システムコール
これは、ユーザ状態プロセスがアクティブにカーネル状態に切り替えることを要求する方法であり、ユーザ状態プロセスは、システム呼び出し申請を通じてオペレーティングシステムが提供するサービスプログラムを使用して作業を完了する.例えば、前例のfork()は、実際には新しいプロセスを作成するシステム呼び出しを実行する.一方、システム呼び出しのメカニズムの核心は、Linuxのint 80 h割り込みのようなオペレーティングシステムがユーザのために特別に開放した割り込みを使用して実現される.
b.異常
CPUがユーザ状態で実行しているプログラムを実行している間に、予め知られていない異常が発生すると、現在の実行プロセスによってこの異常を処理するカーネル関連プログラムに切り替わり、欠ページ異常などのカーネル状態に移行する.
c.周辺機器の割り込み
周辺機器がユーザから要求された操作を完了すると、対応する割り込み信号がCPUに送信され、CPUは次の実行する命令の実行を一時停止し、割り込み信号に対応する処理プログラムの実行に移行し、以前に実行された命令がユーザ状態のプログラムであれば、この変換の過程は自然にユーザ状態からカーネル状態への切り替えが発生する.例えば、ハードディスクの読み書き操作が完了すると、システムはハードディスクの読み書きの割り込み処理プログラムに切り替えて後続の操作を実行するなどします.
 
この3つの方式は、システムが実行時にユーザ状態からカーネル状態に移行する最も主要な方式であり、システム呼び出しはユーザプロセスが自発的に開始したと考えられ、異常と周辺機器の中断は受動的である.
 
2)具体的な切替操作
トリガ方式から見ると、前述の3つの異なるタイプが存在すると考えられるが、ユーザ状態からカーネル状態への切り替え操作を最終的に実際に完了する上で、関連するキーステップは完全に一致しており、何の違いもなく、システム呼び出しが実際には最終的に割り込みメカニズムで実現されるため、割り込み応答のプロセスを実行することに相当する.異常と割り込みの処理メカニズムも基本的に一致しており,それらの具体的な違いについてはここでは後述しない.割り込み処理メカニズムの詳細と手順については、ここではあまり分析しません.ユーザー・ステータスからカーネル・ステータスに切り替える手順は、主に次のとおりです.
[1]現在のプロセスの記述子から、そのカーネルスタックのss 0およびesp 0情報を抽出する.
[2]ss 0とesp 0が指すカーネルスタックを使用して、現在のプロセスのcs,eip,eflags,ss,esp情報を保存します.
プロセスは、ユーザスタックからカーネルスタックへの切り替えプロセスも完了し、実行を一時停止したプログラムの次の
条指令
[3]割り込みベクトルによって取得された割り込み処理プログラムのcs,eip情報を対応するレジスタにロードし,開始する.
割り込みハンドラを実行すると,カーネル状態のプログラム実行に移行する.
変換元:http://www.cnblogs.com/tangr206/articles/3092225.html