`
coderplay
  • 浏览: 578072 次
  • 性别: Icon_minigender_1
  • 来自: 广州杭州
社区版块
存档分类
最新评论

OTP设计原则:Sys和Proc_Lib

阅读更多

6 Sys and Proc_Lib

The module sys contains functions for simple debugging of processes implemented using behaviours.

There are also functions that, together with functions in the module proc_lib, can be used to implement a special process, a process which comply to the OTP design principles without making use of a standard behaviour. They can also be used to implement user defined (non-standard) behaviours.

Both sys and proc_lib belong to the STDLIB application.<!---->

6.1 Simple Debugging

The module sys contains some functions for simple debugging of processes implemented using behaviours. We use the code_lock example from the gen_event chapter to illustrate this:

% erl
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]

Eshell V5.2.3.6 (abort with ^G)
1> code_lock:start_link([1,2,3,4]).
{ok,<0.32.0>}
2> sys:statistics(code_lock, true).
ok
3> sys:trace(code_lock, true).
ok
4> code_lock:button(4).
*DBG* code_lock got event {button,4} in state closed
ok
*DBG* code_lock switched to state closed
5> code_lock:button(3).
*DBG* code_lock got event {button,3} in state closed
ok
*DBG* code_lock switched to state closed
6> code_lock:button(2).
*DBG* code_lock got event {button,2} in state closed
ok
*DBG* code_lock switched to state closed
7> code_lock:button(1).
*DBG* code_lock got event {button,1} in state closed
ok
OPEN DOOR
*DBG* code_lock switched to state open
*DBG* code_lock got event timeout in state open
CLOSE DOOR
*DBG* code_lock switched to state closed
8> sys:statistics(code_lock, get).
{ok,[{start_time,{{2003,6,12},{14,11,40}}},
{current_time,{{2003,6,12},{14,12,14}}},
{reductions,333},
{messages_in,5},
{messages_out,0}]}
9> sys:statistics(code_lock, false).
ok
10> sys:trace(code_lock, false).
ok
11> sys:get_status(code_lock).
{status,<0.32.0>,
{module,gen_fsm},
[[{'$ancestors',[<0.30.0>]},
{'$initial_call',{gen,init_it,
[gen_fsm,
<0.30.0>,
<0.30.0>,
{local,code_lock},
code_lock,
[1,2,3,4],
[]]}}],
running,
<0.30.0>,
[],
[code_lock,closed,{[],[1,2,3,4]},code_lock,infinity]]}

<!---->

6.2 Special Processes

This section describes how to write a process which comply to the OTP design principles, without making use of a standard behaviour. Such a process should:

System messages are messages with special meaning, used in the supervision tree. Typical system messages are requests for trace output, and requests to suspend or resume process execution (used during release handling). Processes implemented using standard behaviours automatically understand these messages.<!---->

6.2.1 Example

The simple server from the Overview chapter, implemented using sys and proc_lib so it fits into a supervision tree:<!---->

-module(ch4).
-export([start_link/0]).
-export([alloc/0, free/1]).
-export([init/1]).
-export([system_continue/3, system_terminate/4,
write_debug/3]).

start_link() ->
proc_lib:start_link(ch4, init, [self()]).

alloc() ->
ch4 ! {self(), alloc},
receive
{ch4, Res} ->
Res
end.

free(Ch) ->
ch4 ! {free, Ch},
ok.

init(Parent) ->
register(ch4, self()),
Chs = channels(),
Deb = sys:debug_options([]),
proc_lib:init_ack(Parent, {ok, self()}),
loop(Chs, Parent, Deb).

loop(Chs, Parent, Deb) ->
receive
{From, alloc} ->
Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
ch4, {in, alloc, From}),
{Ch, Chs2} = alloc(Chs),
From ! {ch4, Ch},
Deb3 = sys:handle_debug(Deb2, {ch4, write_debug},
ch4, {out, {ch4, Ch}, From}),
loop(Chs2, Parent, Deb3);
{free, Ch} ->
Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
ch4, {in, {free, Ch}}),
Chs2 = free(Ch, Chs),
loop(Chs2, Parent, Deb2);

{system, From, Request} ->
sys:handle_system_msg(Request, From, Parent,
ch4, Deb, Chs)
end.

system_continue(Parent, Deb, Chs) ->
loop(Chs, Parent, Deb).

system_terminate(Reason, Parent, Deb, Chs) ->
exit(Reason).

write_debug(Dev, Event, Name) ->
io:format(Dev, "~p event = ~p~n", [Name, Event]).

Example on how the simple debugging functions in sys can be used for ch4 as well:

% erl
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]

Eshell V5.2.3.6 (abort with ^G)
1> ch4:start_link().
{ok,<0.30.0>}
2> sys:statistics(ch4, true).
ok
3> sys:trace(ch4, true).
ok
4> ch4:alloc().
ch4 event = {in,alloc,<0.25.0>}
ch4 event = {out,{ch4,ch1},<0.25.0>}
ch1
5> ch4:free(ch1).
ch4 event = {in,{free,ch1}}
ok
6> sys:statistics(ch4, get).
{ok,[{start_time,{{2003,6,13},{9,47,5}}},
{current_time,{{2003,6,13},{9,47,56}}},
{reductions,109},
{messages_in,2},
{messages_out,1}]}
7> sys:statistics(ch4, false).
ok
8> sys:trace(ch4, false).
ok
9> sys:get_status(ch4).
{status,<0.30.0>,
{module,ch4},
[[{'$ancestors',[<0.25.0>]},{'$initial_call',{ch4,init,[<0.25.0>]}}],
running,
<0.25.0>,
[],
[ch1,ch2,ch3]]}

<!---->

6.2.2 Starting the Process

A function in the proc_lib module should be used to start the process. There are several possible functions, for example spawn_link/3,4 for asynchronous start and start_link/3,4,5 for synchronous start.

A process started using one of these functions will store information that is needed for a process in a supervision tree, for example about the ancestors and initial call.

Also, if the process terminates with another reason than normal or shutdown, a crash report (see SASL User's Guide) is generated.

In the example, synchronous start is used. The process is started by calling ch4:start_link():

start_link() ->
proc_lib:start_link(ch4, init, [self()]).

ch4:start_link calls the function proc_lib:start_link. This function takes a module name, a function name and an argument list as arguments and spawns and links to a new process. The new process starts by executing the given function, in this case ch4:init(Pid), where Pid is the pid (self()) of the first process, that is the parent process.

In init, all initialization including name registration is done. The new process must also acknowledge that it has been started to the parent:

init(Parent) ->
...
proc_lib:init_ack(Parent, {ok, self()}),
loop(...).

proc_lib:start_link is synchronous and does not return until proc_lib:init_ack has been called.<!----><!---->

6.2.3 Debugging

To support the debug facilites in sys, we need a debug structure, a term Deb which is initialized using sys:debug_options/1:

init(Parent) ->
...
Deb = sys:debug_options([]),
...
loop(Chs, Parent, Deb).

sys:debug_options/1 takes a list of options as argument. Here the list is empty, which means no debugging is enabled initially. See sys(3) for information about possible options.

Then for each system event that we want to be logged or traced, the following function should be called.

sys:handle_debug(Deb, Func, Info, Event) => Deb1

  • Deb is the debug structure.
  • Func is a tuple {Module, Name} (or a fun) and should specify a (user defined) function used to format trace output. For each system event, the format function is called as Module:Name(Dev, Event, Info), where:
    • Dev is the IO device to which the output should be printed. See io(3).
    • Event and Info are passed as-is from handle_debug.
  • Info is used to pass additional information to Func, it can be any term and is passed as-is.
  • Event is the system event. It is up to the user to define what a system event is and how it should be represented, but typically at least incoming and outgoing messages are considered system events and represented by the tuples {in,Msg[,From]} and {out,Msg,To}, respectively.

handle_debug returns an updated debug structure Deb1.

In the example, handle_debug is called for each incoming and outgoing message. The format function Func is the function ch4:write_debug/3 which prints the message using io:format/3.

loop(Chs, Parent, Deb) ->
receive
{From, alloc} ->
Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
ch4, {in, alloc, From}),
{Ch, Chs2} = alloc(Chs),
From ! {ch4, Ch},
Deb3 = sys:handle_debug(Deb2, {ch4, write_debug},
ch4, {out, {ch4, Ch}, From}),
loop(Chs2, Parent, Deb3);
{free, Ch} ->
Deb2 = sys:handle_debug(Deb, {ch4, write_debug},
ch4, {in, {free, Ch}}),
Chs2 = free(Ch, Chs),
loop(Chs2, Parent, Deb2);
...
end.

write_debug(Dev, Event, Name) ->
io:format(Dev, "~p event = ~p~n", [Name, Event]).

<!----><!---->

6.2.4 Handling System Messages

System messages are received as:

{system, From, Request}

The content and meaning of these messages do not need to be interpreted by the process. Instead the following function should be called:

sys:handle_system_msg(Request, From, Parent, Module, Deb, State)

This function does not return. It will handle the system message and then call:

Module:system_continue(Parent, Deb, State)

if process execution should continue, or:

Module:system_terminate(Reason, Parent, Deb, State)

if the process should terminate. Note that a process in a supervision tree is expected to terminate with the same reason as its parent.

  • Request and From should be passed as-is from the system message to the call to handle_system_msg.
  • Parent is the pid of the parent.
  • Module is the name of the module.
  • Deb is the debug structure.
  • State is a term describing the internal state and is passed to system_continue/system_terminate.

In the example:

loop(Chs, Parent, Deb) ->
receive
...

{system, From, Request} ->
sys:handle_system_msg(Request, From, Parent,
ch4, Deb, Chs)
end.

system_continue(Parent, Deb, Chs) ->
loop(Chs, Parent, Deb).

system_terminate(Reason, Parent, Deb, Chs) ->
exit(Reason).

If the special process is set to trap exits, note that if the parent process terminates, the expected behavior is to terminate with the same reason:

init(...) ->
...,
process_flag(trap_exit, true),
...,
loop(...).

loop(...) ->
receive
...

{'EXIT', Parent, Reason} ->
..maybe some cleaning up here..
exit(Reason);
...
end.

<!---->

6.3 User-Defined Behaviours

To implement a user-defined behaviour, write code similar to code for a special process but calling functions in a callback module for handling specific tasks.

If it is desired that the compiler should warn for missing callback functions, as it does for the OTP behaviours, implement and export the function:

behaviour_info(callbacks) ->
[{Name1,Arity1},...,{NameN,ArityN}].

where each {Name,Arity} specifies the name and arity of a callback function.

When the compiler encounters the module attribute -behaviour(Behaviour). in a module Mod, it will call Behaviour:behaviour_info(callbacks) and compare the result with the set of functions actually exported from Mod, and issue a warning if any callback function is missing.

Example:

%% User-defined behaviour module
-module(simple_server).
-export([start_link/2,...]).
-export([behaviour_info/1]).

behaviour_info(callbacks) ->
[{init,1},
{handle_req,1},
{terminate,0}].

start_link(Name, Module) ->
proc_lib:start_link(?MODULE, init, [self(), Name, Module]).

init(Parent, Name, Module) ->
register(Name, self()),
...,
Dbg = sys:debug_options([]),
proc_lib:init_ack(Parent, {ok, self()}),
loop(Parent, Module, Deb, ...).

...

In a callback module:

-module(db).
-behaviour(simple_server).

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

...

分享到:
评论

相关推荐

    分布式应用Erlang:Erlang_OTP_19_win64

    OTP则是Erlang生态系统的核心组成部分,提供了大量的库和设计模式,旨在简化并发、错误处理和系统管理。 Erlang的设计灵感来源于通信领域的实际需求,其并发模型基于轻量级进程(processes),这些进程之间的通信是...

    erl:otp_src_24.0.5.tar.gz

    标题中的"erl:otp_src_24.0.5.tar.gz"指的是Erlang的源码包,其中"otp_src_24.0.5"是Erlang/OTP (Open Telecom Platform) 的24.0.5版本的源代码。Erlang是一种面向并发的、函数式的编程语言,常用于构建高可用性和...

    Erlang_OTP_设计原理 中文版

    5. 系统和进程库(Sys and Proc_lib):Sys和Proc_lib模块提供了支持进程创建和管理的功能,它们是Erlang/OTP中特殊进程的一部分。特殊进程是指那些需要处理系统消息、维护自己的状态、并能够在错误情况下恢复的进程...

    Erlang OTP设计原理文档 中文版本

    `sys_and_proc_lib.html`可能包含了关于系统控制和进程库的详细信息,这些是Erlang OTP底层的基础工具,用于管理和交互进程。 9. 发布(Releases): `releases.html`介绍了如何创建和管理Erlang系统的发布版本,...

    OTP.zip_OTP_OTP .nd pudn_java otp_otp java_verify

    在本项目中,“OTP.zip”是一个压缩包,其中包含了实现OTP生成和验证功能的Java代码。 OTP通常基于时间同步(TOTP)或基于挑战-响应的哈希算法(HMAC)两种方式。在这个"OTP"项目中,可能使用了TOTP,因为它是目前...

    Erlang安装包,版本:otp_win64_24.1.7.exe

    otp_win64_24.1.7.exe

    otp_src_23.3.tar.gz

    OTP(Open Telephony Platform)是Erlang编程语言的核心组件之一,主要负责提供分布式计算、容错和系统监控等功能。Erlang是一种并发性极强、面向进程的编程语言,常用于构建高可用性和可扩展性的系统,尤其在电信、...

    otp_verify_java.rar_OTP_OTPVerify_TOTP_otp算法_一次性 口令

    OTPV(OTP Verify)可能是一个Java库,专门用于执行TOTP(Time-Based One-Time Password)和HOTP(HMAC-Based One-Time Password)验证。TOTP基于时间同步,每隔一定时间(如30秒)会生成一个新的密码,而HOTP则基于...

    OTP.rar_MD5 password_OTP_OTP 加密_otp算法_口令认证

    OTP通常用于企业内部的远程访问、网上银行和其他高安全性的在线服务。 MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,可以将任意长度的信息转化为固定长度的摘要。在这个OTP系统中,MD5被用作加密...

    otp_win64_24.0.zip

    OTP(Open Telecom Platform)是Erlang的核心组件,提供了一整套库、设计原则和工具,旨在帮助开发者构建高效、可靠的系统。 标题"otp_win64_24.0.zip"指的是OTP的Windows 64位版本的24.0发行版的压缩文件。这个...

    otp_src_21.0.tar.gz

    OTP(Open Telecommunications Platform)是Erlang编程语言的核心库,包含了用于构建可靠、分布式系统的一系列工具和库。Erlang是一种动态类型的函数式编程语言,常用于构建高并发、低延迟和容错性极强的系统,尤其...

    pin_code_fields:Flutter软件包,将帮助您生成具有精美设计和动画的PIN码字段。 可以用于OTP或Pin码输入:nerd_face::nerd_face:

    Flutter软件包,将帮助您生成具有精美设计和动画的PIN码字段。 可用于OTP或Pin码输入 :nerd_face: :nerd_face: 特征 :green_heart: 自动将下一个字段集中在键入上,将上一个字段集中在删除上 游标支持 :high_...

    otp-win32_20.1 32位

    2. **OTP**:OTP提供了许多库和设计模式,帮助开发者快速构建可靠和可扩展的系统。它包括了进程管理、分布式计算、错误处理、日志和监控等模块,使得Erlang应用程序能够更好地适应复杂的分布式环境。 3. **otp_win...

    otp_win64 window10安装包

    5. 错误管理和恢复机制:OTP设计了一套强大的错误处理机制,如故障检测、故障隔离和自动恢复,增强了系统的健壮性。 在Windows 10环境下安装OTP,用户需要确保系统满足最低的硬件和软件需求,比如兼容的操作系统...

    otp_src_25.0.3.tar.gz

    OTP(Open Telecommunications Platform)是Erlang编程语言的核心组件之一,它提供了一整套用于构建高度可...同时,Erlang/OTP的设计理念和实践经验也可以启发其他语言和平台的开发者,推动他们改进自己的软件设计。

    otp_22.3_for_windows_64 和RabbitMQ-server-3.8.5安装包

    自己自学RabbitMQ整理出来的资料,windows环境下的erlang和RabbitMQ安装包,版本分别是otp_22.3_for_windows_64和rabbitmq-server-3.8.5(保证不会出现版本冲突) 在官网上下载简直是龟速,所以分享给大家便于下载,...

    otp_win64_21.0.1

    otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1

    otp_22.3_for_windows_64.rar

    【otp_win64_22.3.exe】是OTP 22.3版本的Windows 64位安装程序,专门为RabbitMQ设计。这个版本包含了Erlang编程语言和运行时环境,Erlang是RabbitMQ的基础,其并发模型和故障恢复机制使得RabbitMQ能够处理大量的并发...

    otp_src_25.0.2.tar.gz

    OTP是Erlang的标准库和开发框架,包含了各种工具、库和设计模式,旨在简化大型、可靠和实时系统的开发。 描述中的信息简洁,仅提供了文件名,暗示这是Erlang OTP的源码包,版本号为25.0.2。这表明该文件包含了用于...

    BJOTPViewController:输入OTP变得更简单

    BJOTPViewController 一个非常简单且外观整洁的视图控制器,可让您快速方便地键入OTP。技术支持 :check_mark_button: iOS 11.0以上 :check_mark_button: 迅捷4.0+ :check_mark_button: 人像| 风景 :check_mark_...

Global site tag (gtag.js) - Google Analytics