1

メッセージを見ました:

https://stackoverflow.com/a/4837832/1236509

スーパーバイザー付き:

-module(root_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).

start_link() ->
     {ok, Pid} = supervisor:start_link({local, ?MODULE}, 
          ?MODULE, []),
     erlang:unlink(Pid),
     {ok, Pid}.

init(_Args) ->
     RestartStrategy = {simple_one_for_one, 10, 60},
     ChildSpec = {ch1, {ch1, start_link, []},
          permanent, brutal_kill, worker, [ch1]},
     Children = [ChildSpec],
     {ok, {RestartStrategy, Children}}.

コンソールの man 呼び出しで:

{ok, ChildPid1} = root_sup:start_link().

ChildPid1子 pid が変更された場合、新しい pid を取得するにはどうすればよいので、常にChildPid1正しい pid で使用できますか? 子を作成するスーパバイザの一部にリンクする方法が必要です。

4

1 に答える 1

1

私は 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 のオンライン ドキュメントにも記載されています。

于 2012-10-27T22:32:34.423 に答える