erlang OTP gen_server 图解分析
http://www.hoterran.info/otp-gen_server-sourcecode
在阅读erlang的otp源码gen_server.erl的时候,一直想写点什么,用一种最好的方式表达出来,最终却总是没法表达清楚,困惑之余看到这篇文章,作者用图解的方式,非常清晰明了的表达了我一直想表达的东西,下面是原文链接:
http://www.hoterran.info/otp-gen_server-sourcecode
感谢原创作者热心的分享。
阅读OTP源码可以帮助你写出更好、更健壮的erlang程序.下面一系列文章就gen_server、gen_fsm、supervisor的源码进行分析, 从erlang级别解释其工作原理, 所有的完整流程图在这里, 第一次写erlang方面博文有错误请帮忙指出.
为什么从gen_server它开始, 因为gen_fsm和它很类似, 而supervsisor本身是一个gen_server.
init

图示为一个叫Mod的模块, 它是一个gen_server程序, 绿色方格为调用进程(客户进程), 黄色方格为spawn出的gen进程(服务进程). 不同的泳道表示函数所隶属的模块, 通过这个图可以清晰的看出各个模块至之间的相互调用, 图是使用gliffy所画。
从左上角的start(Args)开始,gen_server的程序Mod的开始函数都会调用gen_server:start(或者start_link)来创建一个服务进程,gen_server:start内部实际上调用的是gen模块。
gen模块是很多behaviour的基础,对于gen进程的启动和同步操作进行了封装.gen模块使用proc_lib:start来更加安全的spawn出gen进程,然后阻塞在sync_wait这个函数里,等待gen进程的回应.
spawn出的gen进程会执行到Mod模块的init函数。然后会把{ok, Pid}发送给调用进程告知gen进程已经完成准备工作,然后就进入了自己的循环函数loop中,等待调用进程的下次消息。
调用进程接收到{ok,Pid}之后从阻塞里退出并返回。
整个过程简单,但是要清楚哪个函数是被调用进程或者gen进程所执行。
另外要注意start函数的参数是Args,而init函数的入参是[Args],这个很容易出错的地方。
可以调用start/4或者start_link/4给启动的gen进程命名,函数name_register实际调用register函数.
init_it(GenMod, Starter, Parent, Name, Mod, Args, Options) ->
case name_register(Name) of
true ->
init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options);
....
cast

调用进程向gen进程发送cast消息,消息发送之后调用进程并不等待gen进程的消息回馈.
gen进程从loop函数处接受到Request消息,模式匹配后一路执行到Mod:handle_cast函数,处理消息之后,gen进程继续递归执行loop函数等待后续的新消息. 注意handle_cast不能返回{reply,…},否则gen进程会报错退出。
call

调用进程向gen进程发送call消息,和cast不同,调用进程会阻塞在wait_resp_mon函数里等待gen进程的回馈。收到消息后,gen进程会执行Mod:handle_call函数,并把执行的结果Reply直接发送给调用进程,然后自己再次进入循环等待新的消息。
wait_resp_mon(Node, Mref, Timeout) ->
receive
{Mref, Reply} ->
erlang:demonitor(Mref, [flush]),
{ok, Reply};
{'DOWN', Mref, _, _, noconnection} ->
exit({nodedown, Node});
{'DOWN', Mref, _, _, Reason} ->
exit(Reason)
after Timeout ->
erlang:demonitor(Mref),
receive
{'DOWN', Mref, _, _, _} -> true
after 0 -> true
end,
exit(timeout)
end.
默认情况下handle_call的返回是{reply,….}. 而调用进程阻塞在wait_resp_mon的默认超时时间是5s(-define(default_timeout, 5000)).
在spec里看到handle_call的返回值可以是{noreply,…}, 或者gen进程在处理其它事情而达到超时时间, 则调用进程会异常退出, 你也可以在调用gen_server:call/3来设置一个call命令的超时时间.
对于call和cast的命令既可以使用Name也可以使用Pid, gen内部会进行Name到Pid的转化。
call(Name, Label, Request, Timeout)
when is_atom(Name), Timeout =:= infinity;
is_atom(Name), is_integer(Timeout), Timeout >= 0 ->
case whereis(Name) of
Pid when is_pid(Pid) ->
do_call(Pid, Label, Request, Timeout);
- info
可以给gen进程发送任何格式的信息,这类信息没有gen标签,gen进程接收到这类消息会调用gen_server:handle_info来处理消息,处理过程与cast消息一样都不能反馈结果给调用进程,所以如果handle_info返回{reply,…}也会导致gen进程报错退出。
terminate

在handle_*等回调函数处都可以返回{stop,…} 这样使得gen进程执行Mod:terminate, 进行进程退出前的收尾工作, 然后回到主循环gen进程再退出.
erlang OTP gen_server 图解分析的更多相关文章
- Erlang OTP编程初体验——gen_server和行为模式
http://blog.sina.com.cn/s/blog_3fe961ae0101k4p6.html 行为模式其实非常类似于面向对象语言中的接口,至少笔者是这么理解的.OTP行为模式将一些反复出现 ...
- [Erlang 0119] Erlang OTP 源码阅读指引
上周Erlang讨论群里面提到lists的++实现,争论大多基于猜测,其实打开代码看一下就都明了.贴出代码截图后有同学问这代码是哪里找的? "代码去哪里找?",关于Erla ...
- Erlang OTP gen_event
转自:http://www.myexception.cn/program/1569725.html Erlang OTP gen_event (0) 原英文文档:http://www.erlang.o ...
- Erlang/OTP设计原则(文档翻译)
http://erlang.org/doc/design_principles/des_princ.html 图和代码皆源自以上链接中Erlang官方文档,翻译时的版本为20.1. 这个设计原则,其实 ...
- Erlang/OTP:基于Behaviour的回调函数
原始链接:https://blog.zhustec.me/posts/erlang-otp-1-callback-based-on-behaviour OTP 是什么 OTP 的全称是开源电信平台 ( ...
- 理解Erlang/OTP Supervisor
http://www.cnblogs.com/me-sa/archive/2012/01/10/erlang0030.html Supervisors are used to build an hie ...
- [Erlang 0127] Term sharing in Erlang/OTP 上篇
之前,在 [Erlang 0126] 我们读过的Erlang论文 提到过下面这篇论文: On Preserving Term Sharing in the Erlang Virtual Machine ...
- CentOS 6.5安装Erlang/OTP 17.0
CentOS 6.5安装Erlang/OTP 17.0 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Erlang眼下已经是Fedora和Debian/ ...
- Erlang OTP设计原则Gen_Fsm行为[转]
转自: http://www.cnblogs.com/yourihua/archive/2012/05/13/2497776.html 1. Fsm 称为 有限状态机,举个例子,游戏中的怪物称为NPC ...
随机推荐
- Python 极简教程(六)运算符
运算符,我们日常生活中使用的加减乘除,都是运算符的一种.当然这种一般我们称为算术运算符,用于处理数字运算的. 但是在计算机语言中,还有很多的运算符.用于处理不用的情况. 主要有以下几类: 算术运算符 ...
- 各大免费邮箱邮件群发账户SMTP服务器配置及SMTP发送量限制情况
网络产品推广和新闻消息推送时,经常用到的工具就是用客户邮箱发送邮件了,如果是要发送的邮件量非常大的话,一般的建议是搭建自己的邮局服务器,或者是花钱购买专业的邮件群发服务,免费邮箱的SMTP适合少量的邮 ...
- 黑马day01 xml 的解析方式
XML编程:利用java程序去增删改查(CRUD)xml中的数据 解析思想: dom解析 sax解析 基于这两种解析思想市面上就有了非常多的解析api sun jaxp既有dom方式也有sax方式,而 ...
- 学习easyui疑问(三)
今天我学习easyui中碰到的还有一问题是:怎样创建一个表格? 首先,在easyui中文官网上提供的这样一种定义方式: <!--table--> <table id="tt ...
- Altium Designer中原理图和pcb交叉查找
转自:https://wenku.baidu.com/view/53ca06badbef5ef7ba0d4a7302768e9951e76e33.html 再看看:::: 转自:http://blog ...
- 自旋锁spinlock解析
1 基础概念 自旋锁与相互排斥锁有点类似,仅仅是自旋锁不会引起调用者睡眠.假设自旋锁已经被别的运行单元保持.调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁."自旋"一词就 ...
- thinkphp5最最最最简单的ajax实例
thinkphp5最最最最简单的ajax实例 一.总结 一句话总结:页面端使用$.get()方法传递ajax请求,服务器端判断是不是ajax请求,是的话接受参数,进行逻辑处理之后向客户端返回值. 1. ...
- php模拟顺序栈基本操作
php模拟顺序栈基本操作 一.总结 写函数什么永远记住边界情况:比如 echo "栈已满!<br/>" ; 栈已空这种,那就能多考虑几种情况,代码就很正宗了 1.对象 ...
- 【LeetCode】【C++】Linked list cycle 2
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...
- 如何使用google地图的api(整理)
如何使用google地图的api(整理) 一.总结 一句话总结:直接用script标签引google地图api即可. 1.如何使用google地图的api? 页面引用javascript文件<s ...