システムエントリ
カーネルへの入り口はシステムエントリと呼ばれている。
- ハードウェア割込み
- 入力デバイスが処理を契起したり、クロックを使用したタイマー割込みなど、
外的に発生するイベントである。
- ハードウェア割込みは、非同期に発生し、
その時実行しているプロセスの状態に関連しているとは限らない。
- ハードウェアトラップ
- ハードウェアトラップは同期的にも非同期的にも発生するが、
必ずその時実行しているプロセスに関係する。
(例)
0による除算など、不正な数値計算の結果として発生するものが挙げられる。
- ソフトウェアトラップ
- プロセスの再スケジュールやネットワーク処理を速やかに行いたい場合など、
システムが特定のイベント処理を強制する為に使われる。
- ソフトウェアトラップは、プロセスがカーネル内の処理から抜ける際に
必ず検査されるフラグを設定することで実現される。
そのフラグが設定されていると、
カーネルは処理を終了せずにソフトウェア割込みの為のコードを実行する。
- システムコール
- システムコールは、特別な形態のソフトウェアトラップだと考えられる。
- システムコールの契起となる命令が実行されると、
カーネルが特別に処理するハードウェアトラップを発生する
ユーザ空間からカーネル空間へ
状態の保存
- プロセスがトラップや割込みによってカーネルに実行を移した時、
カーネルはイベントの処理を開始する前に、その時の状態を保存する。
- 保存しなければならない状態
- プログラムカウンタ(PC)
- ユーザスタックポインタ(SP)
- 汎用レジスタ
- プロセッサ状態ロングワード
- PCのトラップ命令は、例外スタックフレームの一部に
プログラムカウンタとプロセッサ状態ロングワードを保存する
- ユーザスタックポインタとレジスタ情報は、ソフトウェアトラップハンドラによって
退避しなければならない
- 割込みは、連続する2つの命令の間で発生する可能性があり、
それはその時に実行しているプロセスと全く関係ないこともある
- 状態の保存が不完全だと正しいプログラムが原因不明の理由で異常動作する
可能性がある
フロー
トラップやシステムコールが発生した時、下記に示す手続きが実行される。
- ハードウェアがカーネル特権モードに移行
これにより、メモリのアクセス検査はカーネル特権で行われ、
スタックへの参照はプロセスごとに用意されたカーネルスタックを使い、
特権命令が実行可能となる。
- ハードウェアは、プログラムカウンタ、プロセッサ状態ロングワードに加えて、
トラップの種類を示す情報をプロセス毎のカーネルスタックにプッシュ
- ハードウェアが保存しなかった残りの情報は、アセンブラで記述された関数によって
保存される
exception.s など。具体的には、汎用レジスタとユーザスタックポインタである。
これらも、プロセス毎のカーネルスタック上にプッシュされる。
保存完了後
状態を保存する準備作業が終わると、カーネルはC言語の関数を実行する。
一般のC言語のように、プロセスの状態を破壊することなく汎用レジスタを使用することができる。
入り口
カーネルへの入り口に応じて、3種類のハンドラが用意されている。
- syscall() :システムコールを処理
- trap():システムコール以外のハードウェアトラップとソフトウェアトラップを処理
- ハードウェア割込みに対応するデバイスドライバの割込みハンドラ
- 受け取るパラメータ
ハンドラ | パラメータ |
---|
システムコール | システムコール番号と例外フレーム |
トラップ | トラップのタイプと、そのトラップに関連する浮動小数点や 仮想アドレスについての情報、例外フレーム |
ハードウェア割込み | ユニット番号 |
カーネル空間からユーザ空間へ
システムコールの呼び出し処理が終了すると、保存しておいたユーザプロセスの状態を元に戻し、制御をユーザプロセスへ戻す。
ユーザプロセスへ戻る為の手続きは、カーネルモードへ移行した時の手続きを逆にたどる。
- アセンブラ関数によって、汎用レジスタとユーザスタックポインタを戻す
- プログラムカウンタとプロセッサ状態ロングワードを復帰し、ユーザモードに移行する
これにより、スタックポインタとしてユーザスタックポインタが使われる。
特権命令の実行が禁止され、メモリアクセス検査はユーザレベル権限で行われるようになる
- 実行はユーザプロセスの割込みが発生した次の命令から再開される
参考