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 图解分析的更多相关文章

    1. Erlang OTP编程初体验——gen_server和行为模式

      http://blog.sina.com.cn/s/blog_3fe961ae0101k4p6.html 行为模式其实非常类似于面向对象语言中的接口,至少笔者是这么理解的.OTP行为模式将一些反复出现 ...

    2. [Erlang 0119] Erlang OTP 源码阅读指引

        上周Erlang讨论群里面提到lists的++实现,争论大多基于猜测,其实打开代码看一下就都明了.贴出代码截图后有同学问这代码是哪里找的?   "代码去哪里找?",关于Erla ...

    3. Erlang OTP gen_event

      转自:http://www.myexception.cn/program/1569725.html Erlang OTP gen_event (0) 原英文文档:http://www.erlang.o ...

    4. Erlang/OTP设计原则(文档翻译)

      http://erlang.org/doc/design_principles/des_princ.html 图和代码皆源自以上链接中Erlang官方文档,翻译时的版本为20.1. 这个设计原则,其实 ...

    5. Erlang/OTP:基于Behaviour的回调函数

      原始链接:https://blog.zhustec.me/posts/erlang-otp-1-callback-based-on-behaviour OTP 是什么 OTP 的全称是开源电信平台 ( ...

    6. 理解Erlang/OTP Supervisor

      http://www.cnblogs.com/me-sa/archive/2012/01/10/erlang0030.html Supervisors are used to build an hie ...

    7. [Erlang 0127] Term sharing in Erlang/OTP 上篇

      之前,在 [Erlang 0126] 我们读过的Erlang论文 提到过下面这篇论文: On Preserving Term Sharing in the Erlang Virtual Machine ...

    8. CentOS 6.5安装Erlang/OTP 17.0

      CentOS 6.5安装Erlang/OTP 17.0 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Erlang眼下已经是Fedora和Debian/ ...

    9. Erlang OTP设计原则Gen_Fsm行为[转]

      转自: http://www.cnblogs.com/yourihua/archive/2012/05/13/2497776.html 1. Fsm 称为 有限状态机,举个例子,游戏中的怪物称为NPC ...

    随机推荐

    1. ThinkPHP5.0---删除数据

      删除特定记录 public function delete() { // 获取要删除的对象:关键字为16 $Teacher = Teacher::); // 删除对象 $Teacher->del ...

    2. 【Codeforces Round #447 (Div. 2) C】Marco and GCD Sequence

      [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 把gcd(a[1..n])放在输入的n个数之间. [代码] /* 1.Shoud it use long long ? 2.Have ...

    3. PatentTips - Apparatus and method for a generic, extensible and efficient data manager for virtual peripheral component interconnect devices (VPCIDs)

      BACKGROUND A single physical platform may be segregated into a plurality of virtual networks. Here, ...

    4. JS错误记录 - getStyle代替offset、任意值运动框

      本次练习错误总结: 1. 改变border的宽度,属性名称不是直接写border,而是borderWidth. 2. 运动函数 -- 清除定时器 -- 开启新的定时器.  不是在新定时器开启之后再清除 ...

    5. GO语言学习(十一)Go 语言循环语句

      Go 语言提供了以下几种类型循环处理语句: 循环类型 描述 for 循环 重复执行语句块 循环嵌套 在 for 循环中嵌套一个或多个 for 循环 语法 Go语言的For循环有3中形式,只有其中的一种 ...

    6. C语言深度剖析-----函数

      认清函数的真面目 函数的意义 面向过程的程序设计 函数声明和定义 函数参数 编写代码的时候,不要编写类似先后调用的代码 f(k,k++) C语言中的顺序点 a--&&a  ,& ...

    7. 克隆windows 2008 x64 后网络问题

      克隆windows 2008 x64 后,网卡中配置IP地址192.168.199.40 (NAT 模式) 内网无法ping 通该机器. 使用ipconfig 查看IP显示为 169.254.203. ...

    8. kafka集群操作指南

      目录 kafka集群操作指南 (一)单机版安装 (二)集群安装 (三)集群启停操作 (四)topic相关的操作 (五)某个broker挂掉,本机器可重启 (六)某个broker挂掉且无法重启,需要其它 ...

    9. ORACEL上传BLOB,深度遍历文件夹

      // uploadingDlg.cpp : 实现文件// #include "stdafx.h"#include "uploading.h"#include & ...

    10. 7 Best jQuery & JavaScript PDF Viewer plugin with examples

      In this Post we are providing best jQuery PDF viewer plugin & tutorial with examples.Due to popu ...