• 特殊进程
    • 例子

    特殊进程

    本节将描述如何编写符合OTP设计原理而又不使用标准行为的进程。这样的一种进程要:

    • 以一种可以让进程放入监督树的方式启动,
    • 支持 sys 的 调试功能 ,以及
    • 注意 系统消息 。系统消息是用于监督树中的带有特殊含义的消息。典型的系统消息有跟踪输出的请求、挂起和恢复进程执行的请求(用于发布处理中)。使用标准行为实现的进程会自动处理这些消息。

    例子

    来自 概述 一章中的简单服务器,如果使用 sysproc_lib 实现并放入一个监督树,则为:

    1. -module(ch4).
    2. -export([start_link/0]).
    3. -export([alloc/0, free/1]).
    4. -export([init/1]).
    5. -export([system_continue/3, system_terminate/4,
    6. write_debug/3]).
    7.  
    8. start_link() ->
    9. proc_lib:start_link(ch4, init, [self()]).
    10.  
    11. alloc() ->
    12. ch4 ! {self(), alloc},
    13. receive
    14. {ch4, Res} ->
    15. Res
    16. end.
    17.  
    18. free(Ch) ->
    19. ch4 ! {free, Ch},
    20. ok.
    21.  
    22. init(Parent) ->
    23. register(ch4, self()),
    24. Chs = channels(),
    25. Deb = sys:debug_options([]),
    26. proc_lib:init_ack(Parent, {ok, self()}),
    27. loop(Chs, Parent, Deb).
    28.  
    29. loop(Chs, Parent, Deb) ->
    30. receive
    31. {From, alloc} ->
    32. Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
    33. ch4, {in, alloc, From}),
    34. {Ch, Chs2} = alloc(Chs),
    35. From ! {ch4, Ch},
    36. Deb3 = sys:handle_debug(Deb2, {ch4, write_debug},
    37. ch4, {out, {ch4, Ch}, From}),
    38. loop(Chs2, Parent, Deb3);
    39. {free, Ch} ->
    40. Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
    41. ch4, {in, {free, Ch}}),
    42. Chs2 = free(Ch, Chs),
    43. loop(Chs2, Parent, Deb2);
    44.  
    45. {system, From, Request} ->
    46. sys:handle_system_msg(Request, From, Parent,
    47. ch4, Deb, Chs)
    48. end.
    49.  
    50. system_continue(Parent, Deb, Chs) ->
    51. loop(Chs, Parent, Deb).
    52.  
    53. system_terminate(Reason, Parent, Deb, Chs) ->
    54. exit(Reason).
    55.  
    56. write_debug(Dev, Event, Name) ->
    57. io:format(Dev, "~p event = ~p~n", [Name, Event]).

    以及如何在 ch4 中使用 sys 中的简易调试函数:

    1. % erl
    2. Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]
    3.  
    4. Eshell V5.2.3.6 (abort with ^G)
    5. 1> ch4:start_link().
    6. {ok,<0.30.0>}
    7. 2> sys:statistics(ch4, true).
    8. ok
    9. 3> sys:trace(ch4, true).
    10. ok
    11. 4> ch4:alloc().
    12. ch4 event = {in,alloc,<0.25.0>}
    13. ch4 event = {out,{ch4,ch1},<0.25.0>}
    14. ch1
    15. 5> ch4:free(ch1).
    16. ch4 event = {in,{free,ch1}}
    17. ok
    18. 6> sys:statistics(ch4, get).
    19. {ok,[{start_time,{{2003,6,13},{9,47,5}}},
    20. {current_time,{{2003,6,13},{9,47,56}}},
    21. {reductions,109},
    22. {messages_in,2},
    23. {messages_out,1}]}
    24. 7> sys:statistics(ch4, false).
    25. ok
    26. 8> sys:trace(ch4, false).
    27. ok
    28. 9> sys:get_status(ch4).
    29. {status,<0.30.0>,
    30. {module,ch4},
    31. [[{'$ancestors',[<0.25.0>]},{'$initial_call',{ch4,init,[<0.25.0>]}}],
    32. running,<0.25.0>,[],
    33. [ch1,ch2,ch3]]}