2011-01-29 30 views

Trả lời

13

Tôi đã thực hiện một số nghiên cứu và dưới đây là những gì tôi có.

Thứ nhất, đây là một mô-đun mẫu callback của một giám sát viên:

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

start_link() -> 
    {ok, Pid} = supervisor:start_link({local, ?MODULE}, 
      ?MODULE, []), 
    {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}}. 

Và đây là một module gọi lại của một đứa trẻ sẽ được bổ sung vào cây suprervision động:

-module(ch1). 

-behaviour(gen_server). 

% Callback functions which should be exported 
-export([init/1]). 
-export([handle_cast/2]). 

% user-defined interface functions 
-export([start_link/0]). 

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

init(_Args) -> 
    io:format("ch1 has started (~w)~n", [self()]), 
    % If the initialization is successful, the function 
    % should return {ok,State}, {ok,State,Timeout} .. 
    {ok, ch1State}. 

handle_cast(calc, State) -> 
    io:format("result 2+2=4~n"), 
    {noreply, State}; 
handle_cast(calcbad, State) -> 
    io:format("result 1/0~n"), 
    1/0, 
    {noreply, State}. 

này là cách chúng tôi thường bắt đầu người giám sát:

1> ch_sup:start_link(). 
{ok,<0.33.0>} 

Bây giờ hãy bắt đầu con đầu tiên của chúng tôi rocess:

2> {ok, Child1Pid} = supervisor:start_child(ch_sup, []). 
ch1 has started (<0.35.0>) 
{ok,<0.35.0>} 

Bạn có thể bắt đầu tự động quy trình con; chúng ta hãy bắt đầu một đứa trẻ:

3> {ok, Child2Pid} = supervisor:start_child(ch_sup, []). 
ch1 has started (<0.37.0>) 
{ok,<0.37.0>} 

Bạn có thể thấy rằng các quá trình của chúng tôi đã bắt đầu (lưu ý hai cuối cùng):

4> erlang:processes(). 
[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>,<0.9.0>, 
<0.10.0>,<0.11.0>,<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>, 
<0.16.0>,<0.17.0>,<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>, 
<0.22.0>,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>, 
<0.31.0>,<0.33.0>,<0.35.0>,<0.37.0>] 

Bây giờ chúng ta hãy làm cho quá trình đứa con đầu lòng của chúng tôi làm điều gì đó:

5> gen_server:cast(Child1Pid, calc). 
result 2+2=4 
ok 

Cho đến nay, rất tốt. Bây giờ chúng tôi sẽ làm cho đứa con đầu tiên của chúng tôi đánh giá một số mã xấu:

6> gen_server:cast(Child1Pid, calcbad). 
result 1/0 
ok  
7> 
=ERROR REPORT==== 10-Feb-2011::01:32:15 === 
** Generic server <0.35.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}, 
        {gen_server,handle_msg,5}, 
        {proc_lib,init_p_do_apply,3}]}, 
      ch1State]}, 
     {gen_server,terminate,6}, 
     {proc_lib,init_p_do_apply,3}]} 
ch1 has started (<0.42.0>) 
7> 

Trong báo cáo, bạn có thể thấy rằng phân chia bằng không gây ra ngoại lệ và quá trình đã bị chấm dứt. Nhưng người giám sát sẽ chăm sóc nó và ngay lập tức bắt đầu một tiến trình con khác (lưu ý dòng cuối cùng).

Chúng tôi có thể kiểm tra để đảm bảo rằng quá trình đứa trẻ khác mà chúng tôi bắt đầu trước đó vẫn còn sống (lưu ý <0.37.0>):

7> erlang:processes().     
[<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>,<0.9.0>, 
<0.10.0>,<0.11.0>,<0.12.0>,<0.13.0>,<0.14.0>,<0.15.0>, 
<0.16.0>,<0.17.0>,<0.18.0>,<0.19.0>,<0.20.0>,<0.21.0>, 
<0.22.0>,<0.23.0>,<0.24.0>,<0.25.0>,<0.26.0>,<0.27.0>, 
<0.31.0>,<0.33.0>,<0.37.0>,<0.42.0>] 
8> 

Chúng tôi thậm chí có thể làm cho nó làm điều gì đó cho chúng tôi:

8> gen_server:cast(Child2Pid, calc). 
result 2+2=4 
9> 

Sau đây là các trang hướng dẫn sử dụng Erlang bạn sẽ muốn đọc:

+0

Thank you very much. Và ở đâu my_start_child/0? – 0xAX

+0

@shk: Ồ, đó là 2:22 sáng ở đây, chỉ cần quên để nhớ lại xuất khẩu này :-) Hàm này chứa 'người giám sát: start_child (ch_sup, []). 'Tôi sẽ sửa bài viết. Một điều quan trọng cần đề cập: con bạn nên luôn luôn liên kết với người giám sát, đó là lý do tại sao tôi sử dụng 'gen_server: start_link' trong hàm khởi đầu con, không chỉ' gen_server: start'; nếu không người giám sát sẽ không có cách nào để biết liệu các tiến trình con của nó vẫn đang chạy hay chấm dứt (bình thường hay bất thường). –

+1

"ch_sup" ở đâu? Tôi nghĩ rằng nó nên được "root_sup" – why

7

Trong phần Supervisor Behaviour của phần OTP Design Principles một phần của tài liệu Erlang có ví dụ về cách sử dụng simple_one_for_one và trẻ em động. Tôi khuyên bạn nên sử dụng toàn bộ Nguyên tắc thiết kế vì nó cung cấp nhiều thông tin chi tiết về cách OTP hoạt động.

Các vấn đề liên quan