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进程再退出.

时间: 2024-10-13 08:55:26

erlang OTP gen_server 图解分析的相关文章

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

http://blog.sina.com.cn/s/blog_3fe961ae0101k4p6.html 行为模式其实非常类似于面向对象语言中的接口,至少笔者是这么理解的.OTP行为模式将一些反复出现的模式分成了两个部分,通用部分和具体应用相关的实现部分,这一过程其实就类似于面向对象编程中的抽象出接口的过程.本文给出一个OTP中最常见的行为模式的示例:通用服务器,即gen_server. 编写gen_server回调模块大致包括3相步骤: (1) 确定回调模块的名称: (2) 写接口函数(由客户

启动erlang/OTP里面的Web服务器

erlang OTP是一个完整可靠的大型库,乃前人艰苦卓绝之成就:现在尝试一下里面的application inets的Web服务器httpd,写一段代码调用inets服务: 1 -module(inets_httpd). 2 -export([start/0]). 3 4 start() -> 5 inets:start(), 6 inets:start(httpd, [{bind_address, {192,168,178,130}}, {ipfamily, inet}, {port, 18

erlang使用gen_server实现质数服务器(手打代码,还debug了几个错误)

最近简单了解一下erlang语言,操练了一下书里的例子,有机会debug:下面是主要模块 prime_server,使用gen_server作为behaviour: 1 -module(prime_server). 2 -export([new_prime/1, start_link/0]). 3 4 -behaviour(gen_server). 5 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/

标准 Erlang/OTP 行为

参考资料 http://erlang.shiningray.cn/otp-design-principles/index.html 标准 Erlang/OTP 行为有: gen_server 用于实现 C/S 结构中的服务端. gen_fsm 用于实现有限状态机. gen_event 用于实现事件处理功能. supervisor 用于实现监督树中的督程.

理解Erlang/OTP Supervisor

http://www.cnblogs.com/me-sa/archive/2012/01/10/erlang0030.html Supervisors are used to build an hierarchical process structure called a supervision tree, a nice way to structure a fault tolerant application.                                         

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

之前,在 [Erlang 0126] 我们读过的Erlang论文 提到过下面这篇论文: On Preserving Term Sharing in the Erlang Virtual Machine 地址: http://user.it.uu.se/~kostis/Papers/erlang12_sharing.pdf  摘要:In this paper we describe our experiences and argue through examples why ?attening t

Erlang/OTP 中文手册

http://erldoc.com/ Open Telecom Platform application array asn1rt base64 binary calendar code dbg dict erlang ets file filelib gb_trees gen_tcp inet io lists make maps math mnesia net_adm os proplists random re rpc string sys unicode Erlang并发编程 Erlan

理解Erlang/OTP - Application

http://www.cnblogs.com/me-sa/archive/2011/12/27/erlang0025.html 1>application:start(log4erl). 我们就从这一行命令开始说起吧,回车之后可以把log4erl应用程序启动起来.Erlang/OTP中的能完成特定功能集合的组件被称为application. ,application是Erlang代码和功能组织的形式之一([Erlang 0015]Erlang OTP设计原则).application的设计目的是

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

转自: http://www.cnblogs.com/yourihua/archive/2012/05/13/2497776.html 1. Fsm 称为 有限状态机,举个例子,游戏中的怪物称为NPC,NPC一般有几种状态,比如:静止,移动,死亡,被攻击,攻击英雄等等几个有限的状态,那么我们就可以有限状态机实现NPC的状态变更. 一个有限状态机可以用一个关系式来描述,State(静止状态S1) x Event(英雄进入视野范围事件E) -> Actions(开始移动动作A), State(移动状