1

有一个模块/功能mymodule ,如何在主管行为下多次启动它?

例如,我需要同时启动同一进程(mymodule)的 2 个实例。我将孩子标识符称为child1child2。它们都指向我要启动的mymodule模块。我已经指定了两个不同的函数来启动工作进程“mymodule”的每个实例( start_link1 和 start_link2 )

-module(my_supervisor).

-behaviour(supervisor).

-export([start_link/0, init/1]).

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

init([]) ->
    {ok, {{one_for_one, 10, 10},
          [{child1,
            {mymodule, start_link1, []},
            permanent,
            10000,
            worker,
            [mymodule]}
          ,
           {child2,
            {mymodule, start_link2, []},
            permanent,
            10000,
            worker,
            [mymodule]}
          ]}}.

worker有两个不同的start_link 函数( start_link1 和 start_link2 )用于测试目的:

-module(mymodule).
-behaviour(gen_server).

start_link1() ->
    log_something("at link 1"),
    gen_server:start_link({global, child1}, ?MODULE, [], []).

start_link2() ->
    log_something("at link 2"),
    gen_server:start_link({global, child2}, ?MODULE, [], []).

init([]) ->
    ....

有了上面的内容,我可以在我的日志中看到“在链接 1”的消息,但它确实在任何地方显示“在链接 2”。它在 link1 的实例中也没有执行任何操作:只是明显地死了。

唯一可行的情况是名称“child1”与工作模块名称“mymodule”匹配时。

4

3 回答 3

1

检查文档以获取supervisor:start_link(). 您在此处传入的第一个参数是它用于注册的名称global,它提供全局name -> pid查找。由于这必须是唯一的,因此您的第二个进程无法启动,因为该名称已被占用。

编辑:这里是文档的链接:http ://erldocs.com/R15B/stdlib/supervisor.html?i=5&search=supervisor:start#start_link/3

于 2013-07-21T19:57:38.477 回答
1

还要检查简单的一对一主管重启方案。它允许以更自动化的方式启动具有相同子规范的多个进程。

于 2013-07-22T09:40:55.373 回答
1

正如@MilleBessö 询问的那样,您是否尝试使用两个具有相同注册名称的进程?是否mymodule:start_link以固定名称注册 mymodule 进程?如果是这样,那么尝试启动第二个将导致冲突。您是否正在尝试启动多个my_supervisor主管?然后你也会遇到名字冲突。您还没有包含my_module.

请记住,您只能以一个名称注册一个进程。这适用于本地注册进程和使用global.

编辑:主管也会死吗?

A和所有其他行为在回调完成并返回正确值 ( )gen_server之前不会被视为正确启动。因此,如果出现错误,这将在子进程初始化之前使子进程崩溃,并且主管将放弃。虽然主管可以并且将在孩子死后重新启动孩子,但它确实要求他们都正确启动。来自主管:start_link/3init{ok,State}mymodule:init/1

如果成功创建了主管及其子进程(即,如果所有子进程启动函数返回 {ok,Child}、{ok,Child,Info} 或忽略)该函数返回 {ok,Pid},其中 Pid 是 pid的主管。如果已经存在具有指定 SupName 的进程,则函数返回 {error,{already_started,Pid}},其中 Pid 是该进程的 pid。

如果 Module:init/1 返回忽略,则此函数也返回忽略,并且主管以正常原因终止。如果 Module:init/1 失败或返回不正确的值,则此函数返回 {error,Term} 其中 Term 是包含有关错误信息的术语,并且主管以 Term 的原因终止。

我不知道这是否是问题,但它给出的行为与你得到的相同。

于 2013-07-23T00:14:23.620 回答