在《Erlang OTP 设计原则》中的 “Sys与Proc_Lib” 一节中有如下描述:
怎样算是符合 OTP 设计原理而又不使用标准行为的 “特殊进程”呢?
系统消息是用于监督树中的、带有特殊含义的消息。典型的系统消息有跟踪输出的请求、挂起和恢复进程执行的请求(用于发布处理中)。基于标准行为模式实现的进程会自动处理这些消息。
如何使用 proc_lib 中的函数创建进程?
而 proc_lib:spawn/1 的实现为
可以看出,其比通常调用 erlang:spawn/1 会多出对祖先信息(Parent 和 Ancestors)和函数相关信息(module+name+arity)的处理,而这些信息是监督树所需要的。
模块 proc_lib 中的函数可以用于实现一种特殊进程,遵照 OTP 设计原则,但不使用标准行为。它们也可以用于实现用户自定义的(非标准)行为。
怎样算是符合 OTP 设计原理而又不使用标准行为的 “特殊进程”呢?
- 以一种可以让进程放入监督树的方式启动;
- 支持 sys 的调试功能;
- 关注系统消息 。
系统消息是用于监督树中的、带有特殊含义的消息。典型的系统消息有跟踪输出的请求、挂起和恢复进程执行的请求(用于发布处理中)。基于标准行为模式实现的进程会自动处理这些消息。
如何使用 proc_lib 中的函数创建进程?
- 用 proc_lib 模块中存在的若干函数来启动进程,例如异步启动的 spawn_link/3,4 以及同步启动的 start_link/3,4,5 。
- 使用这些函数中的任何一个启动的进程都会储存监督树所必须的信息。
- 当使用 proc_lib:start_link 以同步方式启动进程时,调用进程直到 proc_lib:init_ack 被调用后才返回,所以必须成对使用。
1
2
3
4
5
6
|
-module(proc_lib).
%% This module is used to
set
some initial information
%%
in
each created process.
%% Then a process terminates the Reason is checked and
%% a crash report is generated
if
the Reason was not expected.
|
而 proc_lib:spawn/1 的实现为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
spawn(F) when is_function(F) ->
Parent = get_my_name(),
Ancestors = get_ancestors(),
erlang:spawn(?MODULE, init_p, [Parent,Ancestors,F]).
init_p(Parent, Ancestors, Fun) when is_function(Fun) ->
put(
'$ancestors'
, [Parent|Ancestors]),
{module,Mod} = erlang:fun_info(Fun, module),
{name,Name} = erlang:fun_info(Fun, name),
{arity,Arity} = erlang:fun_info(Fun, arity),
put(
'$initial_call'
, {Mod,Name,Arity}),
try
Fun()
catch
Class:Reason ->
exit_p(Class, Reason)
end.
|