プロセス1実行編⑥(システムコール) void trap(struct trapframe *tf) (Xv6を読む~OSコードリーディング~)
前回
jupiteroak.hatenablog.com
トップページ
jupiteroak.hatenablog.com
trap.c(一部抜粋)
https://github.com/mit-pdos/xv6-public/blob/master/trap.c#L36
void trap(struct trapframe *tf) { if(tf->trapno == T_SYSCALL){ if(myproc()->killed) exit(); myproc()->tf = tf; syscall(); if(myproc()->killed) exit(); return; } .....
trap関数は、割り込みサービスルーチン、トラップサービスルーチン、システムコールサービスルーチンに相当する処理を行います(xv6 では、3つのサービスルーチンの役割全てをtrap関数が担っています)
ここでは、trap関数のうちシステムコールサービスルーチンに関わる部分のみを説明します。
引数 trapfram構造体へのポインタtf
前回のalltrapsサブルーチンで、ユーザーモードで使用していたハードウェアコンテキストのフレームにおける先頭アドレス値をtrap関数の引数の値としてプッシュしていたので、その引数の値はtrapfram構造体へのポインタtfにセットされています。
これによって、カーネルスタックに退避させてあるユーザモードのハードウェアコンテキストをtralfram構造体として利用することができます。
処理の内容
if(tf->trapno == T_SYSCALL){ ....
カーネルスタックに退避させてある割り込みベクタ番号(tf->trapno)が64(T_SYSCALL)であること→今回の割り込み・例外処理がシステムコールであることを確認します。割り込み・例外処理がシステムコールだった場合は、if文内に入り、システムコールサービスルーチンとしての処理を実行します。
if(myproc()->killed) exit();
myproc()->killedが真となる場合→システムコールを呼び出したプロセスに関連しているプロセスディスクリプタに終了フラグがセットされている場合は、exitシステムコールを呼び出します。
myproc()->tf = tf;
システムコールを呼び出したプロセスに関連しているプロセスディスクリプタのtfメンバに、ユーザーモードで使用していたハードウェアコンテキストのフレームにおける先頭アドレス値を格納します。次の処理で呼び出すsyscall関数内でこのプロセスディスクリプタを使用するので、プロセスディスクリプタから最新のハードウェアコンテキストのフレームを参照できるようにしておきます。
syscall();
システムコールを呼び出します。
if(myproc()->killed) exit();
myproc()->killedが真となる場合→システムコールを呼び出したプロセスに関連しているプロセスディスクリプタに終了フラグがセットされている場合は、exitシステムコールを呼び出します。
return;