UNIX 6th code reading - signalシステムコール

はじめに

今回は13章の続きを見ていきます。

ソフトウェア割り込み周りのソースコードを追っていきます。

今回は本当に単なるメモ状態です。

ssig

ssigはsignalシステムコールを実現します。u.u_signal[n]に値を設定します(u.u_signal[arg1]=arg2)。

  • 3618 : signalシステムコールに対する引数をaに格納。aはu.u_signal[n]のnに対応。
  • 3619-3622 : aが0以下, NSIG(=20)以上, SIGKIL(=9)の場合エラー。SIGKILはssig( )で設定できない。kill( )でないと設定できない(と思う)
  • 3623 : 返り値として前のu.u_signal[a]をユーザプロセスのr0に格納する
  • 3624 : u.u_signal[a]に引数として渡された値を格納する
  • 3625-3626 : カレントプロセスのp_sigがaならば0にリセットしておく。なぜ必要?

kill

killはkillシステムコールを実現します。

ユーザプロセスのr0経由で渡されたpidを持つプロセスに対して引数で渡されたソフトウェア割り込みnを発せさせます。引数に0が渡された場合はproc#0, 1を除いて全てのプロセスいソフトウェア割り込みを発生させます。

  • 3639-3650 : 以下の条件を"満たさない"プロセスに対してpsignalを使ってp_sigを変更する
    • カレントプロセスである
    • 引数が0でなかった場合、指定したプロセスではない
    • 引数が0であった場合、カレントプロセスと同じ制御端末を持たないかproc#0. 1である
    • ユーザがスーパーユーザではなく、ユーザ識別子が合致しない(?)
  • 3651-3652 : 対象プロセスが存在しなかった場合エラー

signal

引数で指定した端末を持つプロセス全てにpsignalを使ってp_sigを設定します。

psignal

引数で指定したプロセスのp_sigを設定します。

  • 3698-3699 : 指定したシグナル種別がNSIG(=20)以上だったエラー
  • 3971-3972 : 現在のp_sigがSIGKILでなければp_sigを変更する。SIGKILは上書きされないというのはここで実現される
  • 3973-3974 : Lions本にもあるが、ここはバグ?p_statだと辻褄が合わない。おそらくp_pri。p_priだとして、PUSER以上にならないように調整。なぜこの調整がここで必要?
  • 3975-3976 : SWAITで寝ていたら起こす。SWAITはsleepで寝る際、優先度が低い(正)ときに設定される

issig

カレントプロセスがソフトウェア割り込みを受け取っているかどうかチェックします。

ソフトウェア割り込み#nを受け取っていた場合でも、u.u_signal[n]に奇数が設定されていた場合はその割り込みを無視します。

  • 3997 : p_sigが1以上の値を持っていたら(ソフトウェア割り込みを受け取っていたら)
    • 3998 : トレースフラグがたっていたら
      • 3999 : stop( )を呼び出す。ここの詳細はよくわかっていないので後で確認する
      • 4000-4001 : stop( )完了後p_sigを確認し、値を持っていなかったらreturn. stop( )の最中にソフトウェア割り込みが解消されている可能性を考慮している?
    • 4003-4004 : u.u_signal[n(=p_sig)]に偶数の値が設定されていたらnをreturnする

psig

カレントプロセスのp_sigに対応したソフトウェア割り込み処理を行う。

issig( )によるチェックが真だった場合に呼び出されます。

if( issig( ) )
  psig( ) ;
  • 4050 : ソフトウェア割り込み(カレントプロセスのp_sig)をリセット
  • 4051 : u.u_signal[n(=p_sig)]に偶数が設定されていたら、その値を割り込み処理手続きとみなして実行する。issig( )でu.u_signal[n]が奇数の場合は無視されているのでu.u_signal[n]!=0で偶数が設定されていると判別できる
    • 4052 : u.u_errorをリセット
    • 4053-4054 : トレースでも不正処理でもなければu.u_signal[n]をリセット
    • 4055-4056 : ユーザプロセスのr6(sp)を2word拡張
    • 4057 : ユーザプロセスのスタックにユーザプロセスのPSを積む
    • 4058 : ユーザプロセスのスタックにPCを積む。割り込み処理からの戻りアドレスになる?
    • 4059 : ユーザプロセスのspが最上段(4057で積んだPS)を指すようにする
    • 4060 : ユーザプロセスのPSのトレースビットをリセット
    • 4061 : ユーザプロセスのPCがu.u_signal[n]で設定した割り込み処理手続きを指すように設定。PCが更新されたので、この命令の後はu.u_signal[n]で設定した割り込み処理手続きを実行する?
    • 4062 : (割り込み処理手続き実行後?)returnする。4057, 4058でスタックにPS, PCを積んでいたので、psig( )実行したポイントに戻る?
  • 4064 : u.u_signal[n]に0が設定されていた場合
    • 4066-4074 : ここに書かれているシグナルを受け取っていた場合
      • 4075 : exit( )の引数のために?u.u_arg[0]にシグナル種別を示すnを格納
      • 4076-4077 : core( )実行し、nの7bit目を1にする。たぶんcoreを実行したことを表すため。
  • 4079 : exit( )の引数のために?u.u_arg[0]を設定。r0(なんの値が入っている?)を8bit左シフトし、下位bitにはn(シグナル種別+core実行したかどうか)を格納する
  • 4080 : exit( )を実行し、プロセスは自分自身を終了させる


処理の流れが掴みにくかったので絵にしてみました。

core

カレントディレクトリにcoreファイルを作成する。ファイル処理などを理解してから戻ってくる予定。今は詳細を追いません。

終わりに

長くなったので今回はここまで。続きは次回のエントリで。