Brokenプロセスはいつ解放されるのか?
数日前にacidについて書いたとき,「Brokenプロセスはいつまで残っているのだろうか?」という疑問が残った.そこで,Brokenプロセス周りについて調べてみた.
Brokenプロセスに関係しそうなコードを探していたら,port/proc.cに,次のようなコードが見つかった.addbrokenは引数で渡されたプロセスをbrokenという構造体に保持しているのだけど,保持するプロセス数はNBROKENでdefineされている4つだけなのだ.実際に前回使ったプログラムで確認してみたが,Brokenプロセスは4つより増えず,古いプロセスから解放されてしまうようだ.したがって,システムがBrokenプロセスだらけになることは避けられるが,なぜ4つになのか(十分?)はわからない...
966: #define NBROKEN 4 967: struct 968: { 969: QLock; 970: int n; 971: Proc *p[NBROKEN]; 972: }broken; 973: 974: void 975: addbroken(Proc *p) 976: { 977: qlock(&broken); 978: if(broken.n == NBROKEN) { 979: ready(broken.p[0]); 980: memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1)); 981: --broken.n; 982: } 983: broken.p[broken.n++] = p; 984: qunlock(&broken); 985: 986: edfstop(up); 987: p->state = Broken; 988: p->psstate = 0; 989: sched(); 990: }
BrokenプロセスがNBROKEN個以上になった場合,一番古いプロセスをレディキューにキューイングして,再度スケジューリングする.おや,Brokenプロセスを再度実行しては問題ではと思われるだろう.
それは,どうやってaddbrokenがどう呼ばれてきたかを見ればわかる.あるプロセスが異常終了する場合,フォールト処理の後,プロセスを終了するために,pexitを呼ぶ.この際,第二引数のfreememが0である必要がある.1127行目からaddbrokenが呼ばれ,プロセスがBroken状態になる.そして,BrokenプロセスがReady状態になってから,再度スケジューリングされた場合は,1127行目の後から処理が再開される.したがって,Moribund状態になり,schedinitでDead状態になる.非常にシンプルでわかりやすい.
1025: void 1026: pexit(char *exitstr, int freemem) 1027: { 1126: if(!freemem) 1127: addbroken(up); 1163: up->state = Moribund; 1164: sched(); 1165: panic("pexit"); 1166: }
これからわかるようにUNIXではコアダンプはまさに検死だけど,Plan9のBrokenプロセスは,瀕死ではあるけど,まだ生きている.
Brokenプロセスをファイルにコアダンプする方法があるのかは,まだ追ってない.procdumpって関数があるけど,メッセージを表示するためのもので,コアを吐くものじゃないな.