查看源代码 proc_lib (stdlib v6.2)
用于异步和同步启动符合 OTP 设计原则的进程的函数。
此模块用于启动符合 OTP 设计原则的进程。具体来说,此模块中的函数由 OTP 标准行为(例如,gen_server
和 gen_statem
)在启动新进程时使用。这些函数还可以用于启动特殊进程,即符合 OTP 设计原则的用户定义进程。有关示例,请参见 OTP 设计原则中的 sys 和 proc_lib 部分。
当进程启动时,会初始化一些有用的信息。父进程的注册名称或进程标识符以及父进程的祖先都与进程中最初调用的函数的信息一起存储。
在“纯 Erlang”中,只有当退出原因是 normal
时,进程才被认为正常终止,而使用 proc_lib
启动的进程,如果退出原因是 shutdown
或 {shutdown,Term}
,也被认为正常终止。shutdown
是在应用程序(监管树)停止时使用的原因。
当使用 proc_lib
启动的进程异常终止时(即,退出原因不是 normal
、shutdown
或 {shutdown,Term}
),会生成一个崩溃报告,该报告由内核设置的默认日志处理程序写入终端。有关在 Erlang/OTP 21.0 之前如何记录崩溃报告的更多信息,请参阅 SASL 用户指南中的SASL 错误日志记录。
与“纯 Erlang”不同,proc_lib
进程不会生成错误报告,这些报告由模拟器写入终端。所有异常都转换为退出,默认的 logger
处理程序会忽略这些退出。
崩溃报告包含先前存储的信息,例如祖先和初始函数、终止原因以及有关其他因该进程终止而终止的进程的信息。
另请参阅
概述
类型
传递给 init_fail/3
的异常。 有关 Class
、Reason
和 Stacktrace
的说明,请参阅 erlang:raise/3
。
spawn 选项的受限集合。 最值得注意的是,monitor
不是这些选项的一部分。
函数
注意
此函数已被弃用,因为
error_logger
不再是 Erlang/OTP 中首选的日志记录接口。Erlang/OTP 21.0 中添加了一个新的 日志记录 API,但仍然可以使用旧的error_logger
处理程序。新的 Logger 处理程序不需要使用此函数,因为格式化回调 (report_cb
) 包含在日志事件的元数据中。
注意
此函数已被弃用,因为
error_logger
不再是 Erlang/OTP 中首选的日志记录接口。Erlang/OTP 21.0 中添加了一个新的 日志记录 API,但仍然可以使用旧的error_logger
处理程序。新的 Logger 处理程序不需要使用此函数,因为格式化回调 (report_cb
) 包含在日志事件的元数据中。
返回 undefined
或使用 proc_lib:set_label/1
为进程 Pid 设置的标签。
此函数与 hibernate/3
BIF 执行相同的操作(并调用该 BIF),但确保当进程唤醒时,异常处理和日志记录继续按预期工作。
等效于 init_ack(Parent, Ret)
,其中 Parent
是调用 start/5
的进程。
此函数只能由通过 start[_link|_monitor]/3,4,5
函数启动的进程使用。它告诉 Parent
进程已初始化自身并已启动。
等效于 init_fail(Parent, Return, Exception)
,其中 Parent
是调用 start/5
的进程。
此函数只能由通过 start[_link|_monitor]/3,4,5
函数启动的进程使用。它告诉 Parent
进程初始化失败,并根据 Exception
立即引发异常。然后,启动函数返回 Ret
。
提取使用此模块中的 spawn 或 start 函数之一启动的进程的初始调用。Process
可以是 pid、整数元组(可以从中创建 pid)或通过 erlang:process_info(Pid)
函数调用获取的进程 Pid
的进程信息。
为当前进程设置标签。主要目的是帮助调试未注册的进程。进程标签可以在工具和崩溃报告中用于标识进程,但它不必像注册名称那样是唯一的或原子。进程标签可以是任何项,例如 {worker_process, 1..N}
。
生成一个新进程,并按照本手册页开头所述对其进行初始化。使用 spawn
BIF 生成进程。
生成一个新进程,并按照本手册页开头所述对其进行初始化。使用 spawn_link
BIF 生成进程。
生成一个新进程,并按照本手册页开头所述对其进行初始化。使用 erlang:spawn_opt
BIF 生成进程。
同步启动新进程。生成进程并等待其启动。
同步启动新进程。生成进程并等待其启动。原子地在新生成的进程上设置链接。
同步启动新进程。生成进程并等待其启动。原子地在新生成的进程上设置监视器。
命令进程以指定的 Reason
退出,并等待其终止。
类型
-type exception() :: {Class :: error | exit | throw, Reason :: term()} | {Class :: error | exit | throw, Reason :: term(), Stacktrace :: erlang:raise_stacktrace()}.
传递给 init_fail/3
的异常。 有关 Class
、Reason
和 Stacktrace
的说明,请参阅 erlang:raise/3
。
-type spawn_option() :: erlang:spawn_opt_option().
-type start_spawn_option() :: link | {priority, erlang:priority_level()} | {fullsweep_after, non_neg_integer()} | {min_heap_size, non_neg_integer()} | {min_bin_vheap_size, non_neg_integer()} | {max_heap_size, erlang:max_heap_size()} | {message_queue_data, erlang:message_queue_data()}.
spawn 选项的受限集合。 最值得注意的是,monitor
不是这些选项的一部分。
函数
-spec format(CrashReport, Encoding) -> string() when CrashReport :: [term()], Encoding :: latin1 | unicode | utf8.
注意
此函数已被弃用,因为
error_logger
不再是 Erlang/OTP 中首选的日志记录接口。Erlang/OTP 21.0 中添加了一个新的 日志记录 API,但仍然可以使用旧的error_logger
处理程序。新的 Logger 处理程序不需要使用此函数,因为格式化回调 (report_cb
) 包含在日志事件的元数据中。
用户自定义的旧版 error_logger
事件处理程序可以使用此函数来格式化崩溃报告。崩溃报告通过 logger
发送,要处理的事件格式为 {error_report, GL, {Pid, crash_report, CrashReport}}
,其中 GL
是发送崩溃报告的进程 Pid
的组领导者 pid。
-spec format(CrashReport, Encoding, Depth) -> string() when CrashReport :: [term()], Encoding :: latin1 | unicode | utf8, Depth :: unlimited | pos_integer().
注意
此函数已被弃用,因为
error_logger
不再是 Erlang/OTP 中首选的日志记录接口。Erlang/OTP 21.0 中添加了一个新的 日志记录 API,但仍然可以使用旧的error_logger
处理程序。新的 Logger 处理程序不需要使用此函数,因为格式化回调 (report_cb
) 包含在日志事件的元数据中。
用户自定义的旧版 error_logger
事件处理程序可以使用此函数来格式化崩溃报告。当 Depth 指定为正整数时,它将在格式字符串中使用,以限制输出,如下所示:io_lib:format("~P", [Term,Depth])
。
返回 undefined
或使用 proc_lib:set_label/1
为进程 Pid 设置的标签。
-spec hibernate(Module, Function, Args) -> no_return() when Module :: module(), Function :: atom(), Args :: [term()].
此函数与 hibernate/3
BIF 执行相同的操作(并调用该 BIF),但确保当进程唤醒时,异常处理和日志记录继续按预期工作。
对于使用 proc_lib
函数启动的进程,请始终使用此函数,而不是 BIF。
-spec init_ack(Ret) -> ok when Ret :: term().
等效于 init_ack(Parent, Ret)
,其中 Parent
是调用 start/5
的进程。
此函数只能由通过 start[_link|_monitor]/3,4,5
函数启动的进程使用。它告诉 Parent
进程已初始化自身并已启动。
函数 init_ack/1
使用先前由启动函数存储的父值。
如果启动的进程既没有调用此函数,也没有调用 init_fail/2,3
,则当启动的进程退出时,或当启动函数超时(如果使用)时,启动函数会返回一个错误元组,请参见 start/3,4,5
。
警告
不要使用此函数返回指示进程启动失败的错误。这样做时,启动函数可以在失败的进程退出之前返回,这可能会阻塞新的启动尝试成功所需的 VM 资源。为此,请使用
init_fail/2,3
。
以下示例说明了如何使用此函数和 proc_lib:start_link/3
-module(my_proc).
-export([start_link/0]).
-export([init/1]).
start_link() ->
proc_lib:start_link(my_proc, init, [self()]).
init(Parent) ->
case do_initialization() of
ok ->
proc_lib:init_ack(Parent, {ok, self()});
{error, Reason} ->
exit(Reason)
end,
loop().
...
等效于 init_fail(Parent, Return, Exception)
,其中 Parent
是调用 start/5
的进程。
此函数只能由通过 start[_link|_monitor]/3,4,5
函数启动的进程使用。它告诉 Parent
进程初始化失败,并根据 Exception
立即引发异常。然后,启动函数返回 Ret
。
有关 Class
、Reason
和 Stacktrace
的描述,请参见 erlang:raise/3
。
警告
不要考虑捕获此函数中的异常。这会破坏其目的。
start[_link|_monitor]/3,4,5
函数启动的进程应以值(将被忽略)或将由此模块处理的异常结束。请参阅 描述。
如果启动的进程既没有调用此函数,也没有调用 init_ack/1,2
,则当启动的进程退出时,或当启动函数超时(如果使用)时,启动函数会返回一个错误元组,请参见 start/3,4,5
。
以下示例说明了如何使用此函数和 proc_lib:start_link/3
-module(my_proc).
-export([start_link/0]).
-export([init/1]).
start_link() ->
proc_lib:start_link(my_proc, init, [self()]).
init(Parent) ->
case do_initialization() of
ok ->
proc_lib:init_ack(Parent, {ok, self()});
{error, Reason} = Error ->
proc_lib:init_fail(Parent, Error, {exit, normal})
end,
loop().
...
-spec initial_call(Process) -> {Module, Function, Args} | false when Process :: dict_or_pid(), Module :: module(), Function :: atom(), Args :: [atom()].
提取使用此模块中的 spawn 或 start 函数之一启动的进程的初始调用。Process
可以是 pid、整数元组(可以从中创建 pid)或通过 erlang:process_info(Pid)
函数调用获取的进程 Pid
的进程信息。
注意
列表
Args
不再包含参数,而是包含与参数数量相同的原子数量;第一个原子是'Argument__1'
,第二个是'Argument__2'
,依此类推。原因是参数列表可能会浪费大量内存,并且如果参数列表包含 fun,则可能无法升级该模块的代码。如果进程是使用 fun 生成的,则
initial_call/1
不再返回 fun,而是返回模块、实现 fun 的本地函数的函数和元数,例如,{some_module,-work/3-fun-0-,0}
(表示 fun 是在函数some_module:work/3
中创建的)。原因是保留 fun 会阻止模块的代码升级,并且可能会浪费大量内存。
-spec set_label(Label) -> ok when Label :: term().
为当前进程设置标签。主要目的是帮助调试未注册的进程。进程标签可以在工具和崩溃报告中用于标识进程,但它不必像注册名称那样是唯一的或原子。进程标签可以是任何项,例如 {worker_process, 1..N}
。
使用 proc_lib:get_label/1
来查找进程描述。
-spec spawn(Node, Module, Function, Args) -> pid() when Node :: node(), Module :: module(), Function :: atom(), Args :: [term()].
生成一个新进程,并按照本手册页开头所述对其进行初始化。使用 spawn
BIF 生成进程。
-spec spawn_link(Node, Module, Function, Args) -> pid() when Node :: node(), Module :: module(), Function :: atom(), Args :: [term()].
生成一个新进程,并按照本手册页开头所述对其进行初始化。使用 spawn_link
BIF 生成进程。
-spec spawn_opt(Fun, SpawnOpts) -> pid() | {pid(), reference()} when Fun :: function(), SpawnOpts :: [erlang:spawn_opt_option()].
-spec spawn_opt(Node, Module, Function, Args, SpawnOpts) -> pid() | {pid(), reference()} when Node :: node(), Module :: module(), Function :: atom(), Args :: [term()], SpawnOpts :: [erlang:spawn_opt_option()].
生成一个新进程,并按照本手册页开头所述对其进行初始化。使用 erlang:spawn_opt
BIF 生成进程。
-spec start(Module, Function, Args, Time, SpawnOpts) -> Ret when Module :: module(), Function :: atom(), Args :: [term()], Time :: timeout(), SpawnOpts :: [start_spawn_option()], Ret :: term() | {error, Reason :: term()}.
同步启动新进程。生成进程并等待其启动。
要指示启动成功,启动的进程必须调用 init_ack(Parent, Ret)
,其中 Parent
是计算此函数的进程,或者调用 init_ack(Ret)
。Ret
然后由此函数返回。
如果进程启动失败,它必须失败;最好通过调用 init_fail(Parent, Ret, Exception)
,其中 Parent
是计算此函数的进程,或者调用 init_fail(Ret, Exception)
。Ret
然后由此函数返回,并且启动的进程将以 Exception
失败。
如果进程在调用 init_ack/1,2
或 init_fail/2,3
之前失败,则此函数返回 {error, Reason}
,其中 Reason
与进程链接 {'EXIT',Pid,Reason}
消息的异常有点相似。
如果 Time
指定为整数,则此函数将等待 Time
毫秒,以便新进程调用 init_ack/1,2
或 init_fail/2,3
,否则该进程将被终止,并且返回 Ret = {error, timeout}
。
如果指定了参数 SpawnOpts
,则将其作为最后一个参数传递给 spawn_opt/4
BIF。
注意
不允许使用生成选项
monitor
。这会导致函数因badarg
原因而失败。使用生成选项
link
将会为生成的进程设置一个链接,就像 start_link/3,4,5 一样。
-spec start_link(Module, Function, Args, Time, SpawnOpts) -> Ret when Module :: module(), Function :: atom(), Args :: [term()], Time :: timeout(), SpawnOpts :: [start_spawn_option()], Ret :: term() | {error, Reason :: term()}.
同步启动新进程。生成进程并等待其启动。原子地在新生成的进程上设置链接。
注意
如果启动的进程被终止或因非
normal
的原因崩溃,则进程链接将终止调用进程,因此除非调用进程捕获退出,否则此函数不会返回。例如,如果此函数超时,它将终止生成的进程,然后该链接可能会终止调用进程。
除了在生成的进程上设置链接之外,此函数的行为类似于 start/5。
当调用进程捕获退出时;如果此函数由于生成的进程退出(任何错误返回)而返回,则此函数会接收(消耗)'EXIT'
消息,即使此函数超时并终止生成的进程时也是如此。
注意
不允许使用生成选项
monitor
。这会导致函数因badarg
原因而失败。
-spec start_monitor(Module, Function, Args, Time, SpawnOpts) -> {Ret, Mon} when Module :: module(), Function :: atom(), Args :: [term()], Time :: timeout(), SpawnOpts :: [start_spawn_option()], Mon :: reference(), Ret :: term() | {error, Reason :: term()}.
同步启动新进程。生成进程并等待其启动。原子地在新生成的进程上设置监视器。
除了在生成的进程上设置监视器之外,此函数的行为类似于 start/5。
返回值是 {Ret, Mon}
,其中 Ret
对应于对 init_ack/1,2
或 init_fail/2,3
的调用中的 Ret
参数,而 Mon
是已设置的监视器的监视器引用。
如果此函数由于生成的进程退出而返回(即返回任何错误值),则将向调用进程传递 'DOWN'
消息,即使此函数超时并终止生成的进程时也是如此。
注意
不允许使用生成选项
monitor
。这会导致函数因badarg
原因而失败。使用生成选项
link
将会为生成的进程设置一个链接,就像 start_link/3,4,5 一样。
-spec stop(Process, Reason, Timeout) -> ok when Process :: pid() | RegName | {RegName, node()}, RegName :: atom(), Reason :: term(), Timeout :: timeout().
命令进程以指定的 Reason
退出,并等待其终止。
如果进程在 Timeout
毫秒内以指定的 Reason
退出,则返回 ok
。
如果调用超时,则会引发 timeout
异常。
如果进程不存在,则会引发 noproc
异常。
此函数的实现基于 terminate
系统消息,并且要求进程正确处理系统消息。有关系统消息的信息,请参见 sys
以及 OTP 设计原则中的 sys 和 proc_lib 部分。
-spec translate_initial_call(Process) -> {Module, Function, Arity} when Process :: dict_or_pid(), Module :: module(), Function :: atom(), Arity :: byte().
函数 c:i/0
和 c:regs/0
使用此函数来呈现进程信息。
此函数提取使用此模块中的某个生成或启动函数启动的进程的初始调用,并将其转换为更有用的信息。Process
可以是 pid、整数元组(可以从中创建 pid)或通过 erlang:process_info(Pid)
函数调用提取的进程 Pid
的进程信息。
如果初始调用是对诸如 gen_server
或 gen_event
之类的系统定义的行为之一进行的,则会将其转换为更有用的信息。如果生成了 gen_server
,则返回的 Module
是回调模块的名称,Function
是 init
(启动新服务器的函数)。
一个 supervisor
和一个 supervisor_bridge
也都是 gen_server
进程。为了返回此进程是 supervisor 以及回调模块名称的信息,Module
为 supervisor
,而 Function
是 supervisor 回调模块的名称。Arity
为 1
,因为 init/1
函数最初在回调模块中被调用。
默认情况下,如果没有找到关于初始调用的信息,则返回 {proc_lib,init_p,5}
。假设调用者知道该进程已使用 proc_lib
模块生成。