2011-12-01 24 views
1

我正在尝试实现一个简单的主管,并让它重新启动子进程,如果他们失败。但是,我甚至不知道如何在监督下产生多个流程!我看着简单的管理者代码在这个网站,发现一些Erlang:在一个主管下产生多个进程

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

start_link() -> 
    {ok, Pid} = supervisor:start_link(echo_sup, []), 
    unlink(Pid). 
init(_Args) -> 
    {ok, {{one_for_one, 5, 60}, 
     [{echo_server, {echo_server, start_link, []}, 
     permanent, brutal_kill, worker, [echo_server]}, 

     {echo_server2, {echo_server2, start_link, []}, 
     permanent, brutal_kill, worker, [echo_server2]}]}}. 

我认为在init()函数把“echo_server2”部分会催生这名主管在另一个进程,但我最终得到一个异常退出:关闭消息。

“echo_server”和“echo_server2”文件都是相同的代码,但名称不同。所以我现在只是感到困惑。

-module(echo_server2). 
-behaviour(gen_server). 

-export([start_link/0]). 
-export([echo/1, crash/0]). 
-export([init/1, handle_call/3, handle_cast/2]). 

start_link() -> 
    {ok,Pid} = gen_server:start_link({local, echo_server2}, echo_server2, [], []), 
    unlink(Pid). 

%% public api 
echo(Text) -> 
    gen_server:call(echo_server2, {echo, Text}). 
crash() -> 
    gen_server:call(echo_server2, crash). 

%% behaviours 
init(_Args) -> 
    {ok, none}. 
handle_call(crash, _From, State) -> 
    X=1, 
    {reply, X=2, State}; 
handle_call({echo, Text}, _From, State) -> 
    {reply, Text, State}. 
handle_cast(_, State) -> 
    {noreply, State}. 

回答

4

首先您需要阅读一些关于OTP/gen_server和OTP/supervisors的文档。你的代码中有很少的错误。

1)在echo_sup模块更改您的START_LINK功能如下:

start_link() -> 
    supervisor:start_link({local, ?MODULE}, ?MODULE, []). 

不知道为什么你的过程已经开始unlink/1之后。

2)在这两个echo_servers改变START_LINK功能:

start_link() -> 
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). 

你不应该改变这个函数的返回值,因为主管预计这一数值之一:

{ok,Pid} | ignore | {error,Error} 
2

你不” t需要两个不同的模块来运行同一台服务器的两个实例。冲突问题是由于子规范中的标签必须是唯一的。它是元组中的第一个元素。所以你可以有这样的东西:

[{echo_server, {echo_server, start_link, []}, 
     permanent, brutal_kill, worker, [echo_server]}, 
    {echo_server2, {echo_server, start_link, []}, 
     permanent, brutal_kill, worker, [echo_server]}]}}. 

为什么你取消链接子进程?主管使用这些链接来监督其子女。你得到的错误是,主管期望启动孩子的功能返回{ok,ChildPid},这就是它如何获得孩子的PID,所以当它得到另一个返回值时,孩子的启动失败,然后放弃自己。全部根据它应该如何工作。

如果你想注册两台服务器,那么你可以修改start_link函数,把名字用作参数并传递,这样你就可以明确地通过子规范传入它。所以:

start_link(Name) -> 
    gen_server:start_link({local, Name}, ?MODULE, [], []). 

[{echo_server, {echo_server, start_link, [echo_server]}, 
     permanent, brutal_kill, worker, [echo_server]}, 
    {echo_server2, {echo_server, start_link, [echo_server2]}, 
     permanent, brutal_kill, worker, [echo_server]}]}}. 

使用模块名作为服务器的注册名称是只是一个约定,只有当你运行的服务器的一个实例的作品。

相关问题