来自控制台的Erlang pids
我看到一条信息: 与主管:来自控制台的Erlang pids,erlang,Erlang,我看到一条信息: 与主管: -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
-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,以便始终可以使用具有正确pid的ChildPid1
?需要链接到主管创建子进程的部分的方法。我不会尝试通过Pid访问子进程,而是使用名称访问子进程,因此无论实际Pid如何,都可以访问该子进程
使用该代码,一种简单的方法是将寄存器(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]
这是一个正确的进程,运行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}]}]}
请注意,这并不保证gen_server:cast/2
s始终会导致执行相应的代码,因为子进程可能刚刚被杀死,而新进程仍然没有启动(实际上已注册)
您可能希望参考卓越网站,了解有关流程注册、主管、OTP等的更多详细信息。在中还可以找到许多详细信息。我不会尝试通过Pid访问子进程,而是使用名称访问子进程,因此无论实际Pid如何,都可以访问该子进程 使用该代码,一种简单的方法是将
寄存器(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]
这是一个正确的进程,运行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}]}]}
请注意,这并不保证gen_server:cast/2
s始终会导致执行相应的代码,因为子进程可能刚刚被杀死,而新进程仍然没有启动(实际上已注册)
您可能希望参考卓越网站,了解有关流程注册、主管、OTP等的更多详细信息。许多细节也可以在中找到。当子进程pid发生变化时,这是因为进程已死亡,所以名称不会指向子进程break吗?实际上,是的,在崩溃和重新启动之间,发送给孩子的消息将丢失。我看不出这对Child1Pid的值有什么影响?谢谢,但我想更新Child1Pid,以便在控制台上传递给孩子函数?通常,简单的一对一策略用于按需启动流程。因此,应用程序生命周期内的进程数是未知的。出于这个原因,我认为在这种情况下为孩子注册不是一个好主意。根据您要执行的操作,您可以要求主管获取活动进程的列表,或者从服务器启动它们,该服务器将运行进程的列表保存在其状态变量中。当子进程pid更改时,这是因为进程已死亡,所以名称不也指向子进程中断吗?实际上,是的,在崩溃和重新启动之间,发送给孩子的消息将丢失。我看不出这对Child1Pid的值有什么影响?谢谢,但我想更新Child1Pid,以便在控制台上传递给孩子函数?通常,简单的一对一策略用于按需启动流程。因此,应用程序生命周期内的进程数是未知的。出于这个原因,我认为在这种情况下为孩子注册不是一个好主意。根据您要执行的操作,您可以要求主管获取活动进程的列表,或者从将运行进程列表保留在其状态变量中的服务器启动这些进程。