2011年4月12日火曜日

Lions' Commentary (11) - 読書会#6 -

再び読書会の記録です。
今回は13章・・・の途中まででした。signalの処理全般とexit、waitの関係あたりなので内容としては重たかった。ので、仕方ないかなぁ、という感じですね。トレースの部分が終わらずに次回へ繰越です。

ssig
Lions本では3625行について明確な答えが得られていない。自分の理解を読書会で話したんだけど、たぶん同意してもらえたと思う。つまり、あるシグナルハンドラを設定する際、その設定よりも前に該当シグナルが発生し、処理待ち状態になっていたならば、新たなハンドラはその過去に発生したシグナルに関して興味を持っていないはず。よって、なかった事にして良い。もちろん丁寧に処理するのであれば、古いハンドラを呼び出してあげれば良いわけだが、例によってコンテキストスイッチのネストは複雑なので、処理せずに済むのであれば処理しないのがベター。もともとKILL以外は最新のシグナル以外は上書きロストする仕様なので、ここは手を抜くのが落とし所として適切。

kill
pidに0を指定して呼び出した時の動作が特殊。今時のUNIXではこの時、呼び出し元プロセスと同group IDを持つプロセス全てにsignalをbroadcastするのが仕様。当時はまだgroup IDの概念がなく、同じttyにぶら下がっているプロセス全てにbroadcastしている。端末でコントロールコードを入力してsignalを飛ばすとき、この機構を使うのが一般的と思われる。

psignal
シグナルハンドラの起動。kill経由で呼び出されるがLions本で指摘?の通り、バグ持ちのようだ。signal番号として負の値を入れて呼び出すと、psigで配列の範囲外を読み出し、ゴミデータをハンドラのアドレスだと思ってハンドラ呼び出しをしてしまう。たぶんOSごと死んでしまうのではなかろうか。
さらに言えば、シグナル番号が範囲外だった時にエラーを返さない。本来ならssig同様に範囲チェックをしてエラーを返すべき。

issig
トレースが有効になっていたらstopを呼び出す。さらにstopでは親プロセスIDが1だった場合(initの子供だった場合)にプロセスを終了する。ここだけ読んでもわからないが、これはプロセスのデバッグ中に親のデバッガプロセスが不正終了した時のためのコード。親が先に死んだ場合、子プロセスはinitの子プロセスとして登録されるというのがUNIXの風習。initがデバッガの代理処理を行うわけにもいかないので、諦めてデバッガプロセスと道連れでデバッグ対象プロセスもexit・・・、というのはやむを得ない処置か。

exit
user構造体の複製をswap領域に作成し、終了コードを保存。全シグナルハンドラを無視に設定して、プロセス領域を開放、ゾンビプロセスになる。その後の処理が読書会の中でも時間をかけて議論された部分。
まず、親プロセスが存在しないと、自分自身をinitプロセスの子プロセスとして登録する。続けて、initプロセスと親プロセスを起こす。最後に未回収の子プロセスをinitプロセスにぶら下げ直して、コンテキストスイッチ。initプロセスを起こすのは、initにぶら下げた子プロセスが既にexitしてwait待ちになっている可能性があるため。親プロセスを起こすのは、自身の終了をwaitで待ってブロックしている時のため。全者の理由を解読するのに時間がかかった。
プロセスを起こす処理はwakeup(&proc[1])とwakeup(p)。waitで寝るとき、自身のproc構造体のポインタが要因として利用されるため、このような記述でそれぞれwait中のinitプロセス、親プロセスを起こすことになる。

wait
ゾンビ化したプロセスを最終的に回収して上げるのがwait。UNIXではfork、execで生成されたプロセスは、exitで実行イメージを開放し、終了コードを含むuser構造体をswap領域に退避する。最後に親がwaitで回収する事でuser構造体を含む全てのプロセスリソースが開放可能となる。逆に言えば親のwaitで回収されないプロセスはゾンビプロセスとして永久にswap領域内に居残り続ける。PDP-7 UNIXの頃はこのあたりの終了コードのやり時も、もう少し汎用性の高いプロセス間通信で行われていた模様。ところが、実際には決まりきった使い方しかされていなかったので、マルチプログラミングの改善時に、終了コードの受け渡しだけに特化したexit、waitの実装になった模様。このあたりの様子はUNIX原典に書かれてます。

7shiさんのデモ
いや、これは熱い。デモを見せてもらったんだけど、Silverlightのファンになりました(言い過ぎ)。しかし、良く作りこまれていて。Ken Thompsonとかが見たら泣いて喜ぶんじゃないだろうか。コマンドライン版はbinfmt_miscに登録すると素敵かもしれない。あとqemuにマージされたりすると、もっと素敵。
そうそう、simh上の動作は標準出力が遅い〜みたいな話があったけど、たぶんコンソールから出力するにあたり、kl.cのドライバ経由でtty.cのコードが動き、デバイスのBUSY状態を見ながら出力している&BUSY状態がデバイスの実時間をシミュレートしているためではないかと思います。

0 件のコメント: