最新のすべてのCPUには、現在実行中のマシン命令を中断する能力があります。何も起こらなかったように、後で実行を再開できるように、十分な状態(通常、常にではありませんが、常にスタック)を保存します(中断された命令は通常ゼロから再開されます)。次に、割り込みハンドラの実行を開始します。これは単なるマシンコードですが、CPUが事前にその場所を認識できるように特別な場所に配置されます。割り込みハンドラーは、常にオペレーティングシステムのカーネルの一部です。これは、最大の特権で実行され、他のすべてのコンポーネントの実行を監視するコンポーネントです。1,2
割り込みは同期、つまり、現在実行中の命令が行った何かに対する直接の応答としてCPU自体によってトリガーされることを意味します。または、非同期は、ネットワークに到着するデータなどの外部イベントのために予測できない時間に発生することを意味します港。一部の人々は非同期割り込みに「割り込み」という用語を予約し、代わりに同期割り込みを「トラップ」、「障害」、または「例外」と呼びますが、これらの単語はすべて他の意味を持っているため、「同期割り込み」に固執します。
現在、ほとんどの最新のオペレーティングシステムにはプロセスの概念があります。最も基本的には、これはコンピューターが複数のプログラムを同時に実行できるメカニズムですが、オペレーティングシステムがメモリ保護を構成する方法の重要な側面でもあります。まだすべてではありません)最新のCPU。それは仮想メモリと一緒に行きます、これはメモリアドレスとRAM内の実際の場所の間のマッピングを変更する機能です。メモリ保護により、オペレーティングシステムは各プロセスに専用のRAMチャンクを与え、それだけがアクセスできるようにします。また、オペレーティングシステム(プロセスの代わりに動作する)が、RAMの領域を読み取り専用、実行可能、協調プロセスのグループ間で共有などとして指定することもできます。カーネル。3
CPUが許可するように構成されている方法でのみ各プロセスがメモリにアクセスする限り、メモリ保護は見えません。プロセスがルールに違反すると、CPUは同期割り込みを生成し、カーネルに処理を依頼します。プロセスが実際にルールに違反することはなく、プロセスの続行を許可する前にカーネルのみが何らかの作業を行う必要があることが定期的に発生します。たとえば、RAMのスペースを他の何かのために解放するためにプロセスのメモリのページをスワップファイルに「排除」する必要がある場合、カーネルはそのページにアクセス不可とマークします。プロセスが次にそれを使用しようとすると、CPUはメモリ保護割り込みを生成します。カーネルはスワップからページを取得し、元の場所に戻し、再びアクセス可能としてマークし、実行を再開します。
しかし、プロセスが実際にルールを破ったと仮定します。RAMがマップされたことのないページにアクセスしようとしたか、マシンコードを含まないなどのマークが付けられたページを実行しようとしました。一般に「Unix」として知られるオペレーティングシステムのファミリはすべて、この状況に対処するために信号を使用します。4シグナルは割り込みに似ていますが、ハードウェアによって生成され、カーネルによってフィールド化されるのではなく、カーネルによって生成され、プロセスによってフィールド化されます。プロセスはシグナルハンドラを定義できます独自のコードで、それらがどこにあるかをカーネルに伝えます。これらのシグナルハンドラは、必要に応じて実行され、通常の制御フローを中断します。シグナルにはすべて数字と2つの名前があり、1つは不可解な頭字語で、もう1つはややわかりにくいフレーズです。プロセスがメモリ保護ルールに違反したときに生成されるシグナルは(慣例により)番号11であり、その名前はSIGSEGV
「セグメンテーション違反」です。5,6
シグナルと割り込みの重要な違いは、すべてのシグナルにデフォルトの動作があることです。オペレーティングシステムがすべての割り込みのハンドラーの定義に失敗すると、それはOSのバグであり、CPUが欠落しているハンドラーを呼び出そうとするとコンピューター全体がクラッシュします。ただし、プロセスには、すべてのシグナルのシグナルハンドラを定義する義務はありません。カーネルがプロセスのシグナルを生成し、そのシグナルがデフォルトの動作のままになっている場合、カーネルは先に進み、デフォルトを実行し、プロセスに影響を与えません。ほとんどのシグナルのデフォルトの動作は、「何もしない」または「このプロセスを終了し、おそらくコアダンプを生成する」です。SIGSEGV
後者の1つです。
要約すると、メモリ保護ルールを破ったプロセスがあります。CPUはプロセスを中断し、同期割り込みを生成しました。カーネルはその割り込みをSIGSEGV
処理し、プロセスのシグナルを生成しました。プロセスがなかったと仮定しようではないためにシグナルハンドラを設定しSIGSEGV
、そのカーネルはプロセスを終了することとなる、デフォルトの動作を行います。これには、_exit
システムコールと同じ効果があります。開いているファイルが閉じられたり、メモリが割り当て解除されたりします。
この時点まで、人間が見ることのできるメッセージは何も印刷されておらず、シェル(より一般的には、終了したばかりのプロセスの親プロセス)はまったく関与していません。親SIGSEGV
ではなく、ルールを破ったプロセスに行きます。ただし、シーケンスの次のステップは、子プロセスが終了したことを親プロセスに通知することです。これは、親がすでにの一つを使用して、この通知を待っているとき、最も簡単なのとなっているいくつかの異なる方法で起こることができるwait
システムコール(wait
、waitpid
、wait4
、など)。その場合、カーネルはそのシステムコールを返すだけで、終了ステータスと呼ばれるコード番号を親プロセスに提供します。7終了ステータスは、子プロセスが終了した理由を親に通知します。この場合、SIGSEGV
シグナルのデフォルトの動作のために子が終了したことがわかります。
親プロセスは、メッセージを出力することにより、イベントを人間に報告できます。シェルプログラムはほとんど常にこれを行います。あなたはcrsh
それを行うためのコードが含まれていませんが、Cライブラリルーチンがあるため、それは、とにかく起こるsystem
、フル機能のシェルを実行している/bin/sh
「フードの下」、。このシナリオcrsh
の祖父母です。親プロセス通知はによってフィールド化され/bin/sh
、通常のメッセージを出力します。その後/bin/sh
、何もすることがないため、それ自体が終了し、Cライブラリの実装system
はその終了通知を受け取ります。の戻り値を調べることにより、コードで終了通知を確認できます。system
; しかし、中間プロセスで消費されたため、孫プロセスがセグメンテーション違反で死亡したことはわかりません。
脚注
一部のオペレーティングシステムは、カーネルの一部としてデバイスドライバーを実装していません。しかし、全ての割り込みハンドラは、まだカーネルの一部でなければならない、そしてハードウェアは何もできないためので、メモリ保護を設定するコードを行いますが、これらの事を行うには、カーネルを。
カーネルよりもさらに特権のある「ハイパーバイザー」または「仮想マシンマネージャー」と呼ばれるプログラムがあるかもしれませんが、この答えの目的のために、それはハードウェアの一部と考えることができます。
カーネルはプログラムですが、プロセスではありません。それは図書館のようなものです。すべてのプロセスは、独自のコードに加えて、カーネルのコードの一部を時々実行します。カーネルコードのみを実行する「カーネルスレッド」が多数存在する場合がありますが、ここでは関係ありません。
1、あなたはもう対処しなければならない可能性があるだけでOS ができないのUnixの実装と考えることは、当然のことながら、Windowsのです。この状況では信号を使用しません。(実際に、それはありません持っている信号を、Windows上の<signal.h>
インターフェースは完全にCライブラリによって偽造されています。)これは「と呼ばれる何か使用構造化例外処理の代わりを」。
のSIGBUS
代わりに、いくつかのメモリ保護違反が発生します(「バスエラー」)SIGSEGV
。2つの間の線は指定不足で、システムによって異なります。のハンドラを定義するプログラムを作成したSIGSEGV
場合は、おそらく同じハンドラを定義することをお勧めしますSIGBUS
。
「セグメンテーションフォールト」は、元のUnixを実行したコンピューターの1つ、おそらくPDP-11によってメモリ保護違反に対して生成された割り込みの名前でした。「セグメンテーション」はメモリ保護の一種ですが、今日では「セグメンテーション障害」という用語は一般的にあらゆる種類のメモリ保護違反を指します。
子プロセスが終了したことを親プロセスに通知する他のすべての方法では、親プロセスが呼び出しwait
て終了ステータスを受け取ります。何か他のものが最初に起こるだけです。
crsh
この種の実験には素晴らしいアイデアです。それとその背後にあるアイデアについて私たち全員に知らせてくれてありがとう。