第九回スパルタンプログラミング
zombieの駆逐とラグランジアン
場末の中華屋(おいしい)に連れてっても、屈託の無い笑顔を見せる嫁をみつけようと誓ったのは先週だった。
3人で雨の中をふらふら歩いて太平閣へ行ったら休み、おいしい春巻きの食べられない週末なんて。。orz
そいで一社の中華屋へ、店員がこぼしたビールをさっと避けてやった。もし避けきれなかったらお代は安くなったのだろうか。 そんな今週のできごと。
やりたいこと
- forkの子プロセスのzombieをお片づけ(UNP vol.1の5.9節から)
zombieが残るのは、子プロセスのプロセスID、終了状態、CPU時間やメモリ使用量といった資源の利用状況などの子プロセスに関する情報を親プロセスが後で取得できるようにするため。
zombieを処理するには
子プロセスに対し、waitを実行するとzombie processを消滅させることができる。 そのためには親プロセスでSIGCHLDを捕捉するシグナルハンドラを設定し、シグナルハンドラでwaitを呼び出せばいい。
signalとは
コンピュータにおいて一般的に割り込みと行っているものを、Cではシグナルと呼んでいる。ソフトウェア割り込みとも呼ばれる。
シグナルは普通、asynchronouslyに発生する。よって、いつシグナルが発生するかを前もって知ることはできない。
シグナルは - あるプロセスから別のプロセスへ - カーネルからプロセスへ 送ることができる。
シグナルの種類
- SIGKILL:捕捉不能
- SIGSTOP:捕捉不能
- SIGIO:捕捉にはプロセス側で付加的処理が必要
- SIGPOLL:捕捉にはプロセス側で付加的処理が必要
- SIGURG:捕捉にはプロセス側で付加的処理が必要
- SIGCHLD:捕捉可能。SIGCHLDはプロセスが終了したときに、終了したプロセスの親プロセスにカーネルが必ず送る
シグナルの処理(disposition)の設定方法
シグナルを受けて処理するには、以下の2つの方法がある。
- signal関数を使用する
- 第一引数:シグナル名
- 第二引数:関数へのポインタ or SIG_IGN or SIG_DEF
- sigaction関数を使う(UNP vol.1はこっちを推奨p.120)
設定値には、以下がある。
- SIG_IGN:シグナルの発生をignoreできる。ただし、SIGKILLとSIGSTOPは無視できない
- SIG_DFL:シグナルに対するdefault動作を設定できる。
割り込まれたシステムコールの処理(UNP vol.1 p121)
プロセスがslow system callでブロックしている最中にシグナルの捕捉がおきてシグナルハンドラから制御が戻る場合、システムコールはEINTRエラーを返す可能性がある。
「いくつかの」カーネルは、「いくつかの」システムコールに対して割り込まれたシステムコールを自動的に再実行する。
シグナルを捕捉するプログラムの移植性を向上させるには、slow system callがEINTRを返す場合に備えよう!とのこと。
備えが無いとコード上も非自明に見えると思う。
疑問
void sig_chld_unpver(int signo) { pid_t pid; int stat; while( (pid = waitpid(-1, &stat, WNOHANG)) > 0) fprintf(stderr,"child %d tarminated\n",pid); return; }
whileとWNOHANGを使うとブロッキングせずにSIG_CHLDを処理できるけれど、「Unixのシグナルはキューイングされない」ならとりこぼすことはあるのではないかと思ったり。
言葉
おまけ:ラグランジアンって何がうれしいの?
運動エネルギーとポテンシャルエネルギーをとっかかりにしてラグランジアンを書く!(束縛条件を忘れずに!)
すると、最小作用の原理を認めて変分すれば運動方程式(オイラーラグランジュ方程式)が出てくる。
また、無限小変換(座標の変換)によって、ラグランジアンの作用と形式が変化しないとすると保存則が出てくる。
ただ注意として、異なるラグランジアン(座標系は同じ)から同じオイラーラグランジュ方程式が出ることがある。 この場合は、算数的な操作に惑わされずに物理的に意味のあるラグランジアンかを確かめる。