erlang supervisor simple_one_for_one实例

http://www.cnblogs.com/little-ant/p/3196201.html

simple_one_for_one vs one_for_one:

相同点:

这种Restart Strategy和one_for_one基本相同(即当一个child process挂掉后,仅仅重启该child process 而不影响其他child process)。

异同点:

1, simple_one_for_one supvisor启动时不会启动任何子进程,所有子进程都只能通过调用 supervisor:start_child(Sup, Args) 来动态启动。

2, simple_one_for_one supvisor持有child process的定义,并有一个dict存放数据, 其实就是如干个child process,共享一份数据。

3, 一个simple_one_for_one supervisor只有一个(single)simple_one_for_one的定义, 也就是说它只能生产出一种类型worker process。

 

supervisor:start_child(Sup, Args) :

    Sup:  Supervisor的Pid或者registered Name.

    Args: 当supervisor的类型是simple_one_for_one时,Args会追加到spec的参数中。

例如:

复制代码
-module(simple_sup).

-behaviour(supervisor).



-export([start_link/0]).

-export([init/1]).



start_link() ->

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



init(_Args) ->

  {M, F, A} = _Args,

    {ok, {{simple_one_for_one, 0, 1},

          [{M, {M, F, A},

            temporary, brutal_kill, worker, [M]}]}}.
复制代码

调用supervisor:start_child(simple_sup, Args)后,最终启动子进程的代码会是:apply(M, F, A++Args).

调用supervisor:start_child(Sup, Args)可能会遇到的错误:

1, noproc: 可能的原因是在调用supervisor:start_link时没写参数{local, ?MODULE},即上面代码红色部分,此时进程Sup并不存在,所以会产生

                 noproc错误。

2,undef: 可能的原因是A++Args后,与child process的start_link函数参数不一致。

 

实例代码:

     实例包含两部分,一是监控普通进程(normal_process.erl),二是监控gen_server进程(gen_server_process.erl)。

common.hrl

%%-define(CALL, normal_process).

-define(CALL, gen_server_process).

simple_sup.erl

复制代码
-module(simple_sup).

-behaviour(supervisor).



-export([start_link/0]).

-export([init/1]).



-include("common.hrl").



start_link() ->

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



init(_Args) ->

    {ok, {{simple_one_for_one, 0, 1}, 

          [{?CALL, {?CALL, start_link, []},

          temporary, brutal_kill, worker, [?CALL]}]}}.
复制代码

normal_process.erl

复制代码
-module(normal_process).



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



start_link() ->

    proc_lib:start_link(?MODULE, start_loop, [self()]).



start_loop(Parent) ->

    proc_lib:init_ack(Parent, {ok, self()}),

    loop().



loop() ->

    receive

        Args ->

            io:format("~p~n", [Args])

    end.
复制代码

gen_server_process.erl

复制代码
-module(gen_server_process).

-behaviour(gen_server).

-export([start_link/0]).



%% gen_server callbacks

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,

         terminate/2, code_change/3]).



%% interface

-export([start/0, stop/0, echo/1]).



%% interface implement

start()      -> start_link().

stop()       -> gen_server:call(?MODULE, stop).

echo(String) -> gen_server:call(?MODULE, {echo, String}).



%% gen_server callbacks implement

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



init([]) ->

    {ok, 0}. 



handle_call({echo, String}, _From, Tab) ->  

    Reply = String,

    {reply, Reply, Tab};



handle_call(stop, _From, Tab) ->

    {stop, normal, stopped, Tab}.



handle_cast(_Msg, State) -> {noreply, State}.

handle_info(_Info, State) -> {noreply, State}.

terminate(_Reason, _State) -> ok. 

code_change(_OldVsn, State, _Extra) -> {ok, State}.
复制代码

编译命令:

c(simple_sup).

c(normal_process).

c(gen_server_process).

测试命令:

simple_sup:start_link().

supervisor:start_child(simple_sup, []).

测试通过start_child启动普通进程:

修改common.hrl:-define(CALL, normal_process). 执行编译命令 + 测试命令。

测试通过start_child启动gen_server进程:

修改common.hrl:-define(CALL, gen_server_process). 执行编译命令 + 测试命令。

你可能感兴趣的:(erlang)