【转载】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:
- -module(mymodule).
- start_link() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
- ...
- crash() ->
- gen_server:cast(?MODULE, crash).
- ...
- handle_cast(crash,State) ->
- {stop, error, State};
- ...
Let's spawn of those, and try to link our shell to it:
- 1> self().
- <0.31.0>
- 2> mymodule:start_link().
- {ok,<0.34.0>}
- 3> mymodule:crash().
- =ERROR REPORT==== 30-Dec-2012::15:36:47 ===
- ** Generic server a terminating
- ** Last message in was {'$gen_cast',crash}
- ** When Server state == []
- ** Reason for termination ==
- ** error
- ** exception exit: error
- 4> self().
- <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
:
- 1> process_flag(trap_exit, true).
- false
- 2> self().
- <0.31.0>
- 3> mymodule:start_link().
- {ok,<0.35.0>}
- 4> mymodule:crash().
- ok
- 5>
- =ERROR REPORT==== 30-Dec-2012::15:51:20 ===
- ** Generic server mymodule terminating
- ** Last message in was {'$gen_cast',crash}
- ** When Server state == []
- ** Reason for termination ==
- ** error
- 5> self().
- <0.31.0>
- 6> receive X->X end.
- {'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:
- unlink/1: Removes the link between 2 processes.
- spawn_link/1: Spawns a new process, linked.
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:
- -module(mymodule).
- start() ->
- gen_server:start({local, ?MODULE}, ?MODULE, [], []).
- ...
- start_link() ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
- ...
- crash() ->
- gen_server:cast(?MODULE, crash).
- ...
- handle_cast(crash,State) ->
- {stop, error, State};
- ...
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:
- 1> self().
- <0.31.0>
- 2> mymodule:start().
- {ok,<0.34.0>}
- 3> process_flag(trap_exit, true).
- false
- 4> erlang:monitor(process, mymodule).
- #Ref<0.0.0.43>
- 5> mymodule:crash().
- ok
- =ERROR REPORT==== 30-Dec-2012::16:21:29 ===
- ** Generic server mymodule terminating
- ** Last message in was {'$gen_cast',crash}
- ** When Server state == []
- ** Reason for termination ==
- ** error
- 6> receive X->X end.
- {'DOWN',#Ref<0.0.0.43>,process,{mymodule,nonode@nohost},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:
- spawn_monitor/1: Spawns a new process, monitored.
- demonitor/1: Removes a 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
【转载】Erlang 中 link 和 monitor 的区别的更多相关文章
- [转载]C++中声明与定义的区别
C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...
- CSS中link与import的区别
一.import的用法 1,在html文件中 <style type="text/css"> @import url(http://www.dreamdu.com/st ...
- AngularJS自定义Directive中link和controller的区别
在AngularJS中,自定义Directive过程中,有时用link和controller都能实现相同的功能.那么,两者有什么区别呢? 使用link函数的Directive 页面大致是: <b ...
- AngularJs 指令 directive中link,controller 的区别
其实严格来讲,link和controller是完全不同的概念,这里讲区别有点牵强. angular指令中,带有link和controller两个函数,很多人在写指令的时候不知道是写在link里 还是c ...
- HTML网页设计中 link 和 @import 的区别
页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:link和@import.外部引用CSS两种方式link和@import的方式分别是 ...
- 转载http中302与301的区别
http://blog.csdn.net/qmhball/article/details/7838989 一.官方说法301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于 ...
- 【对比分析三】CSS中 link 和@import 的区别
1). link 是 XHTML 标签,无兼容问题: @import 是在 CSS2.1 提出的,只有IE5以上才能识别. 2). 语法结构不同. link (链接式)只能放入HTML源码中,语法 ...
- 外部引用CSS中 link与@import的区别
差别1:link属于XHTML标签,而@import完全是CSS提供的一种方式. link标签除了可以加载CSS外,还可以做很多其它的事情,比如定义RSS,定义rel连接属性等,@import就只能加 ...
- [转载]jquery中attr和prop的区别
在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答案很多.这里谈谈我的心得,我的心得很简单: ...
随机推荐
- SQL小技巧小知识
1.[ ]的使用 当我们所要查的表是系统关键字或者表名中含有空格时,需要用[]括起来,例如新建了两个表,分别为user,user info,那么select * from user和select * ...
- dom 中事件
阻止表单提交: function aa(){ return false; } function bb(event){ event.preventDefault(); } 事件不再派发: <!DO ...
- php扩展开发初探
2015年2月26日 15:44:41 原因: 想用PHP实现一个布隆过滤器算法, 其中要用到位运算, 但是PHP的内置的int类型不给力, 不能支持大整数的位运算 数据一旦太大, 就会变为浮点数表示 ...
- php字符串处理总结
php字符串处理是php基础中重要的一部分,总结并整理了一下 1.最简单的,字符串输出单引号和双引号的区别(定义字符串用单引号和双引号都可以) $str='hello'; echo "str ...
- 【JAVA、C++】LeetCode 002 Add Two Numbers
You are given two linked lists representing two non-negative numbers. The digits are stored in rever ...
- POJ1704 Georgia and Bob (阶梯博弈)
Georgia and Bob Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %I64d & %I64u Subm ...
- UVA11806-Cheerleaders(容斥原理+二进制)
In most professional sporting events, cheerleaders play a major role in entertaining the spectators. ...
- Step deep into GLSL
1 Lighting computation is handled in eye space(需要根据眼睛的位置来计算镜面发射值有多少进入眼睛), hence, when using GLSL (GP ...
- mysql自增字段重排 或 归零
由于删除了某些记录行,所以自增字段不连续了.重排或归零的方法:方法1:truncate table 你的表名//这样不但重新定位自增的字段,而且会将表里的数据全部删除,慎用!方法2:delete fr ...
- 如何在Win8系统上建立WIFI热点
1.首先将鼠标移到桌面左下角,单击右键,在弹出的快捷菜单中找到“命令提示符(管理员)”,点击 2.点击后,系统就以管理员权限打开了命令提示符,在命令提示符中输入以下命令“netsh wlan set ...