一个常见的情况: supervisor 下启动了N个子进程,如何访问这些子进程?
一般可以通过两种方式:
1.通过PID
所有的子进程在创建完成后都会有相应的PID,将这些个PID存到本地的表中,需要时通过PID去访问进程。
2.通过进程名
在注册一个进程的时候为其指定相应的名称,需要时通过进程名访问进程。
下面为一个简单的例子:
建立一个supervisor ,采用simple_one_for_one 的启动策略:
-module(superMan). -behaviour(supervisor). -export([start_sup/0,open_wc/1]). -export([ init/1 ]). -define(SERVER, ?MODULE). start_sup()-> supervisor:start_link({local,superMan}, ?MODULE, []) . init([]) -> AChild = {wcroom, {thewc,start_link,[]}, temporary, 2000, worker, [thewc]}, {ok, {{simple_one_for_one,0,1}, [AChild]}}. open_wc(Num)-> supervisor:start_child(superMan,[Num]) .
子进程的模块定义如下:
-module(thewc).
-behaviour(gen_server).
-export([lashi/2,start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-record(state, {num}).
start_link(Num)-> gen_server:start_link({local,list_to_atom(integer_to_list(Num))},?MODULE,[Num],[])
.
init([Num]) ->
{ok, #state{num=Num}}.
handle_call({lashi,Name}, From, State) ->
#state{num=Num}=State,
io:format("man ~p is lashing in wc~p",[Name,Num]),
{reply, ok, State};
handle_call(Request, From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(Msg, State) ->
{noreply, State}.
handle_info(Info, State) ->
{noreply, State}.
terminate(Reason, State) ->
ok.
code_change(OldVsn, State, Extra) ->
{ok, State}.
lashi({pid,Ref},Name)->
gen_server:call(Ref, {lashi,Name})
;
lashi(Num,Name)->
gen_server:call(list_to_atom(integer_to_list(Num)), {lashi,Name})
.
测试方法如下:
start()-> {ok,Pid}=superMan:start_sup(), unlink(Pid), {ok,Pid1}=superMan:open_wc(1), thewc:lashi({pid,Pid1}, "wang"), {ok,Pid2}=superMan:open_wc(2), thewc:lashi(2, "zhang") .
测试结果如下:
man "wang" is lashing in wc1
man "zhang" is lashing in wc2ok
需要注意的是:在gen_server:call(Module,Args) 的时候,如果要调用的进程是注册在本地的,则Module 直接为进程名对应的Atom 值。只有这个进程注册为gloable 时才需要指定Module 为{gloable,Module},否则会报nodedown异常。