天天看點

【原創】調用 proc_lib:spawn/1 和 erlang:spawn/1 有什麼差別

在《erlang otp 設計原則》中的 “sys與proc_lib” 一節中有如下描述: 

子產品 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 被調用後才傳回,是以必須成對使用。

在 stdlib\src\proc_lib.erl 中有如下說明 

<a href="http://my.oschina.net/moooofly/blog/281997#">?</a>

1

2

3

4

5

6

<code>-module(proc_lib).</code>

<code>%% this module is used to</code><code>set</code> <code>some initial information</code>

<code>%%</code><code>in</code> <code>each created process.</code>

<code>%% then a process terminates the reason is checked and</code>

<code>%% a crash report is generated</code><code>if</code> <code>the reason was not expected.</code>

而 proc_lib:spawn/1 的實作為 

7

8

9

10

11

12

13

14

15

16

17

<code>spawn(f) when is_function(f) -&gt;</code>

<code>    </code><code>parent = get_my_name(),</code>

<code>    </code><code>ancestors = get_ancestors(),</code>

<code>    </code><code>erlang:spawn(?module, init_p, [parent,ancestors,f]).</code>

<code>init_p(parent, ancestors, fun) when is_function(fun) -&gt;</code>

<code>    </code><code>put(</code><code>'$ancestors'</code><code>, [parent|ancestors]),</code>

<code>    </code><code>{module,mod} = erlang:fun_info(fun, module),</code>

<code>    </code><code>{name,name} = erlang:fun_info(fun, name),</code>

<code>    </code><code>{arity,arity} = erlang:fun_info(fun, arity),</code>

<code>    </code><code>put(</code><code>'$initial_call'</code><code>, {mod,name,arity}),</code>

<code>    </code><code>try</code>

<code>   </code><code>fun()</code>

<code>    </code><code>catch</code>

<code>   </code><code>class:reason -&gt;</code>

<code>   </code><code>exit_p(class, reason)</code>

<code>    </code><code>end.</code>

      可以看出,其比通常調用 erlang:spawn/1 會多出對祖先資訊(parent 和 ancestors)和函數相關資訊(module+name+arity)的處理,而這些資訊是監督樹所需要的。