私は Pid で子にアクセスしようとはしませんが、代わりに子プロセスを名前で登録/2するので、実際の Pid に関係なくアクセスできます。
参照する回答のコードを使用して、これを行う簡単な方法はregister(ch1, self()),
、子の init プロシージャに追加することです。これにより、次のようになりch1.erl
ます。
init(_Args) ->
io:format("ch1 has started (~w)~n", [self()]),
% register a name to this process
register(child, self()),
{ok, ch1State}.
これにより、子の pid がself()
名前に登録されchild
ます。動作することがわかります。
1> root_sup:start_link().
{ok,<0.34.0>}
2> supervisor:start_child(root_sup, []).
ch1 has started (<0.36.0>)
{ok,<0.36.0>}
3> lists:filter(fun(X) -> X == child end, registered()).
[child]
という名前でプロセスが登録されていますchild
。
4> gen_server:cast(child, calc).
result 2+2=4
からコードを実行するのは正しいプロセスch1.erl
です。
悪いコードを呼び出して、このプロセスをクラッシュさせましょう。
5> gen_server:cast(child, calcbad).
result 1/0
ok
ch1 has started (<0.41.0>)
6>
=ERROR REPORT==== 28-Oct-2012::01:31:30 ===
** Generic server <0.36.0> terminating
** Last message in was {'$gen_cast',calcbad}
** When Server state == ch1State
** Reason for termination ==
** {'function not exported',
[{ch1,terminate,
[{badarith,
[{ch1,handle_cast,2,[{file,"ch1.erl"},{line,27}]},
{gen_server,handle_msg,5,
[{file,"gen_server.erl"},{line,607}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]},
ch1State],
[]},
{gen_server,terminate,6,[{file,"gen_server.erl"},{line,722}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,227}]}]}
それで子供、プロセス<0.36.0>
がクラッシュし、新しい子供<0.41.0>
が故人の職務を引き継ぎ始めました<0.36.0>
。この新しいプロセスは同じ名前で登録されているため、calc
再び機能します。
6> gen_server:cast(child, calc).
result 2+2=4
ok
gen_server:cast/2
これは、 s が常に対応するコードの実行をもたらすことを保証するものではないことに注意してください。
プロセス登録、スーパーバイザー、OTP などの詳細については、Joe Armstrong による優れたProgramming Erlang: Software for a Concurrent Worldを参照することをお勧めします。多くの詳細は、OTP のオンライン ドキュメントにも記載されています。