来自控制台的Erlang pids

时间:2012-10-27 22:03:34

标签: erlang

我看到了消息:

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?需要链接到创建孩子的主管的一部分。

1 个答案:

答案 0 :(得分:1)

我不会尝试通过Pid访问孩子,而是register/2名称下的子进程,因此无论实际的Pid如何都可以访问。

使用代码from the answer you reference,一种简单的方法是将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}.

这会将子self()的pid注册到名称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总是会导致执行相应的代码,因为孩子可能刚刚被杀死,而新进程仍未启动(事实上已注册)。 / p>

有关流程注册,主管,OTP等的更多详细信息,您可能需要参考优秀的Programming Erlang: Software for a Concurrent World by Joe Armstrong。许多细节也可以在the online documentation of OTP中找到。