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]).
...
分享到:
相关推荐
erl最新版本,erl 23版本 和24版本 属于大版本更新了,有些23版本高性能模块已经不适用24版本,我博客有说明,需要的可以去主页看下。
Erlang是一种通用的面向并发的编程语言,它有瑞典电信设备制造商爱立信所辖的CS-Lab开发, 目的是创造一种可以应对大规模并发活动的编程语言和运行环境。
Flutter软件包,将帮助您生成具有精美设计和动画的PIN码字段。 可用于OTP或Pin码输入 :nerd_face: :nerd_face: 特征 :green_heart: 自动将下一个字段集中在键入上,将上一个字段集中在删除上 游标支持 :high_...
Generate & Verify OTP Server
实现了一次性口令认证系统,采用MD5算法进行加密,得到口令的校验码
OTP进程池应用程序_Erlang_Makefile_下载.zip
otp_win64_26.0安装包
BJOTPViewController 一个非常简单且外观整洁的视图控制器,可让您快速方便地键入OTP。技术支持 :check_mark_button: iOS 11.0以上 :check_mark_button: 迅捷4.0+ :check_mark_button: 人像| 风景 :check_mark_...
otp_win64_24.1.7.exe
Erlang/OTP
errol:以OTP方式编排RabbitMQ消费者:open_mailbox_with_raised_flag:
otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1otp_win64_21.0.1
解压后为:otp_src_21.0.tar.gz,附带下载地址
0.63 npm i react-native-otp-field@0.0.7一个可在android和iOS上运行的小型库。道具道具类型描述长度数字OTP长度价值细绳OTP字符串onChange 功能当以新值作为参数更改OTP时调用textFieldStyle 目的文字栏位样式...
OPT一次性动态口令验证算法。根据动态支持TOTP和HOTP验证。
RabbitMQ所需otp_win64_22.3.exe Windows 64位安装文件,解决官网下载慢问题,免积分
自己自学RabbitMQ整理出来的资料,windows环境下的erlang和RabbitMQ安装包,版本分别是otp_22.3_for_windows_64和rabbitmq-server-3.8.5(保证不会出现版本冲突) 在官网上下载简直是龟速,所以分享给大家便于下载,...
otp_win64_20.3otp_win64_20.3otp_win64_20.3otp_win64_20.3otp_win64_20.3
otp-win32_20.1 32位,里面时安装文件,自己找的时候方便一些
Erlang最新版本 25.0.3 windows 安装文件 解压直接安装 5个币-----------------------------------------------------------------------------------------------------------------------------------------------...