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}}.

在控制台人员调用中:

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

当子 pid 更改时,如何ChildPid1获得新的 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()到 namechild 我们可以看到它的工作原理:

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/2s 总是导致相应代码的执行,因为子进程可能刚刚被杀死,而新进程仍未启动(实际上已注册)。

您可能想参考Joe Armstrong 撰写的优秀 Programming Erlang: Software for a Concurrent World,以了解有关进程注册、监督员、OTP 等的更多详细信息。许多细节也可以在OTP 的在线文档中找到。

于 2012-10-27T22:32:34.423 回答