【转载】Erlang 中 link 和 monitor 的区别

Link and Monitor differences

原文地址

Introduction

link/1 and monitor/2 are 2 different ways of notifying (or know) that a process died. Thing is, these are really very different in nature and these differences are not widely understood by beginners. So let‘s shed some light on this subject!

Linking to a process

Links are what makes it possible to have supervisor trees. As stated in the Error Handling section of the processes reference manual:

Erlang has a built-in feature for error handling between processes. Terminating processes will emit exit signals to all linked processes, which may terminate as well or handle the exit in some way.

The signal in question is the exit signal, and the links make this signal propagate through processes (i.e: up in the supervisor hierarchy). By default, this signal makes your processes terminate as well. Assume the following code:

view plaincopy to clipboardprint?

  1. -module(mymodule).
  2. start_link() ->
  3. gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
  4. ...
  5. crash() ->
  6. gen_server:cast(?MODULE, crash).
  7. ...
  8. handle_cast(crash,State) ->
  9. {stop, error, State};
  10. ...

Let‘s spawn of those, and try to link our shell to it:

view plaincopy to clipboardprint?

  1. 1> self().
  2. <0.31.0>
  3. 2> mymodule:start_link().
  4. {ok,<0.34.0>}
  5. 3> mymodule:crash().
  6. =ERROR REPORT==== 30-Dec-2012::15:36:47 ===
  7. ** Generic server a terminating
  8. ** Last message in was {‘$gen_cast‘,crash}
  9. ** When Server state == []
  10. ** Reason for termination ==
  11. ** error
  12. ** exception exit: error
  13. 4> self().
  14. <0.36.0>

As you can see, using gen_server:start_link/4 automatically creates a link between our shell and the newly started process. So when this new process terminates, our shell gets an exit signal, also crashes, but it gets automatically restarted (note how the self() code returned 2 different pids).

The Receiving Exit Signals section of the processes reference manual gives some more information:

The default behaviour when a process receives an exit signal with an exit reason other than normal, is to terminate and in turn emit exit signals with the same exit reason to its linked processes. An exit signal with reason normal is ignored.

A process can be set to trap exit signals by calling:

process_flag(trap_exit, true)

When a process is trapping exits, it will not terminate when an exit signal is received. Instead, the signal is transformed into a message {‘EXIT‘,FromPid,Reason} which is put into the mailbox of the process just like a regular message.

Let‘s now try the same thing, but capturing the exit signal with process_flag/2

:

view plaincopy to clipboardprint?

  1. 1> process_flag(trap_exit, true).
  2. false
  3. 2> self().
  4. <0.31.0>
  5. 3> mymodule:start_link().
  6. {ok,<0.35.0>}
  7. 4> mymodule:crash().
  8. ok
  9. 5>
  10. =ERROR REPORT==== 30-Dec-2012::15:51:20 ===
  11. ** Generic server mymodule terminating
  12. ** Last message in was {‘$gen_cast‘,crash}
  13. ** When Server state == []
  14. ** Reason for termination ==
  15. ** error
  16. 5> self().
  17. <0.31.0>
  18. 6> receive X->X end.
  19. {‘EXIT‘,<0.35.0>,error}

As you can see, the shell didn‘t died, but got a message instead. Cool!

To sum up, and to quote the Processes entry in the OTP reference manual:

    • Two processes can be linked to each other. A link between two processes Pid1 and Pid2 is created by Pid1 calling the BIF link(Pid2) (or vice versa).
    • Links are bidirectional and there can only be one link between two processes. Repeated calls to link(Pid) have no effect.
    • The default behaviour when a process receives an exit signal with an exit reason other than normal, is to terminate and in turn emit exit signals with the same exit reason to its linked processes.
    • An exit signal with reason normal is ignored.

As a final note to links, there are a couple of interesting functions to know about:

Monitoring a process

Monitors are not links, they are a more relaxed way of knowing what happened to a process.

They use messages instead of signals, and these messages are not propagated like signals, so nothing happens to your process when a monitored process exits (except that you get a new message in your mailbox). Also, they are unidirectional and allow you to establish as many "monitors" as you want (remember how links limited the number of links between 2 processes to just 1). Quoting the manual:

An alternative to links are monitors. A process Pid1 can create a monitor for Pid2 by calling the BIF erlang:monitor(process, Pid2). The function returns a reference Ref.

If Pid2 terminates with exit reason Reason, a ‘DOWN‘ message is sent to Pid1:

{‘DOWN‘, Ref, process, Pid2, Reason}

Monitors are unidirectional. Repeated calls to erlang:monitor(process, Pid) will create several, independent monitors and each one will send a ‘DOWN‘ message when Pid terminates.

Now, to the very same source code we tried above, let‘s modify it to add a start/0 function:

view plaincopy to clipboardprint?

  1. -module(mymodule).
  2. start() ->
  3. gen_server:start({local, ?MODULE}, ?MODULE, [], []).
  4. ...
  5. start_link() ->
  6. gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
  7. ...
  8. crash() ->
  9. gen_server:cast(?MODULE, crash).
  10. ...
  11. handle_cast(crash,State) ->
  12. {stop, error, State};
  13. ...

Note the new start/0 call that uses gen_server:start/4 instead of gen_server:start_link/4, so we can avoid having our shell linked to the new process when trying it.

Let‘s try it in the shell:

view plaincopy to clipboardprint?

  1. 1> self().
  2. <0.31.0>
  3. 2> mymodule:start().
  4. {ok,<0.34.0>}
  5. 3> process_flag(trap_exit, true).
  6. false
  7. 4> erlang:monitor(process, mymodule).
  8. #Ref<0.0.0.43>
  9. 5> mymodule:crash().
  10. ok
  11. =ERROR REPORT==== 30-Dec-2012::16:21:29 ===
  12. ** Generic server mymodule terminating
  13. ** Last message in was {‘$gen_cast‘,crash}
  14. ** When Server state == []
  15. ** Reason for termination ==
  16. ** error
  17. 6> receive X->X end.
  18. {‘DOWN‘,#Ref<0.0.0.43>,process,{mymodule,[email protected]},error}

So our shell, while still was informed about the exit of the other process, didn‘t die (because it didn‘t got an exit signal).

A couple of interesting functions related to monitoring:

To link or to monitor: That is the question

So this brings up the question: should I link to or monitor my processes? Of course the answer is 42.. I mean, it depends. Use link if you:

      • Have a dependency on a process (i.e: you can‘t run if a specific process dies). This fits great into supervisor trees.
      • Have a bidirectional dependency, where a parent can‘t run if the child dies, and you also want to kill the child if the parent dies in turn.
      • Only need 1 link between processes (remember that if A and B are linked, all subsequent calls to link/2 will be ignored).
      • You are a supervisor, or you want some kind of physical relationship between your processes in your architecture (i.e: you actually need to die or restart or try something out to fix the situation that led to the death of your child.

Use monitor if you:

      • Just want to know if a specific process is running, but it‘s ok for you to continue execution without it (i.e: you can just send an alarm and keep going).
      • Don‘t need a bidirectional relation (i.e: you want A to know about B dying but you don‘t need B to know about A).
      • You are an external process, just interested in the faith of a particular process
时间: 2024-10-05 07:42:25

【转载】Erlang 中 link 和 monitor 的区别的相关文章

转载http中302与301的区别

http://blog.csdn.net/qmhball/article/details/7838989 一.官方说法301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于: 301 redirect: 301 代表永久性转移(Permanently Moved).302 redirect: 302 代表暂时性转移(Temporarily Moved ). 这是很官方的说法,那么它们的区别到底是什么呢? 二.现实中的差异2.1.对于用户301,302对用户来说没有区别

CSS中link和@import的区别

你对CSS中link和@import的区别是否熟悉,这里和大家分享一下,@import  属性用来指定导入的外部样式表及目标设备类型, link除了调用CSS外还可以有其他作用譬如声明页面链接属性,声明目录,rss等等,而@import就只能 调用CSS. CSS中link和@import有什么区别? 定义  ◆link元素 HTML和XHTML都有一个结构,它使网页作者可以增加于HTML文档相关的额外信息.这些额外资源可以是样式化信息(CSS).导航助手.属于另 外形式的信息(RSS).联系信

AngularJS自定义Directive中link和controller的区别

在AngularJS中,自定义Directive过程中,有时用link和controller都能实现相同的功能.那么,两者有什么区别呢? 使用link函数的Directive 页面大致是: <button id="addItem">Add Item</button><without-Controller datasource="customers" add="addCustomer"></without-

外部引用CSS中 link与@import的区别

差别1:link属于XHTML标签,而@import完全是CSS提供的一种方式. link标签除了可以加载CSS外,还可以做很多其它的事情,比如定义RSS,定义rel连接属性等,@import就只能加载CSS了. 差别2:加载顺序的差别.当一个页面被加载的时候(就是被浏览者浏览的时候),link引用的CSS会同时被加载,而@import引用的CSS会等到页面全部被下载完再被加载. 差别3:兼容性的差别.由于@import是CSS2.1提出的所以老的浏览器不支持,@import只有在IE5以上的才

[转载]js中__proto__和prototype的区别和关系

首先,要明确几个点:1.在JS里,万物皆对象.方法(Function)是对象,方法的原型(Function.prototype)是对象.因此,它们都会具有对象共有的特点.即:对象具有属性__proto__,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法. 2.方法(Function)方法这个特殊的对象,除了和其他对象一样有上述_proto_属性之外,还有自己特有的属性--原型属性(prototype),这个属性是一个指针,

(转载)jquery中attr和prop的区别

最近一直在学习jquery checkbox选中事件判断,总结来说可以使用以下这种方式判断一个checkbox是否选中: if ( elem.checked ) if ( $( elem ).prop( "checked" ) ) if ( $( elem ).is( ":checked" ) ) 第一个是js原生代码,特别注意的是$( elem ).attr( "checked" )是没有办法判定一个checkbox是否会选中.jquery官网

转载:C#中ref和out的区别浅析

这篇文章主要介绍了C#中ref和out的区别浅析,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢,需要的朋友可以参考下 在C#中通过使用方法来获取返回值时,通常只能得到一个返回值.因此,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢? MSDN:        ref 关键字使参数按引用传递.其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中.若要使用 ref 参数,则方法定义和调用方法都

oracle中函数和存储过程的区别和联系【转载竹沥半夏】

oracle中函数和存储过程的区别和联系[转载竹沥半夏] 在oracle中,函数和存储过程是经常使用到的,他们的语法中有很多相似的地方,但也有自己的特点.刚学完函数和存储过程,下面来和大家分享一下自己总结的关于函数和存储过程的区别. 一.存储过程 1.定义 存储过程是存储在数据库中提供所有用户程序调用的子程序,定义存储过程的关键字为procedure. 2.创建存储过程 create [or replace] procedure 存储过程名 [(参数1 类型,参数2 out 类型……)] as

【转载】Spring中DispatcherServlet与ContextLoaderListener的区别

昨天在写springmvc的时候,在web.xml中配置了DispatcherServlet,如下: <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>