在分析 gen_server (或者是gen_fsm )之前,首先应该弄明白,gen 这个module .

 -module(gen).
-compile({inline,[get_node/1]}). %%%-----------------------------------------------------------------
%%% This module implements the really generic stuff of the generic
%%% standard behaviours (e.g. gen_server, gen_fsm).
%%%
%%% The standard behaviour should export init_it/6.
%%%-----------------------------------------------------------------

也就是说,gen 这个模块 gen_server ,gen_fsm 的基础.

PS. 无特殊说明,以下提到的gen_server 都指代gen_server 和 gen_fsm .

export func

 -export([start/5, start/6, debug_options/1,
call/3, call/4, reply/2]).

gen 模块导出了以上这些函数,其中:

start/N 是用于spawn gen_server 进程. 基本的流程是使用proc_lib:spawn(_link) 创建新的process, 并以init_it 作为初始化函数, 继而回调 gen_server 模块中的init_it函数, 完成gen_server 模块的init .

call/N 是用于gen_server call func 的实现,也就是 gen_server:call 的实际调用.

reply/2 的实现相对“简单”,即调用bif erlang:'!'/2 发送消息. 但是这个函数的作用很大, 之后会一一提到.

start/N

start/5 用于创建无名gen_server , start/6 用于创建指定name 的gen_server .

     start(GenMod, LinkP, Name, Mod, Args, Options)
GenMod :: gen_server | gen_fsm
LinkP :: nolink | link
Name :: {local, atom()} | {global, term()} | {via, atom(), term()} %% 就是指定的name
Mod :: atom() %% 就是使用了gen_server behaviour 的模块名
Args :: term() %% Mod 模块 init func 的初始参数
Options :: [{timeout, Timeout} | {debug, [Flag]} | {spawn_opt, OptionList}] %% 这个参数是用来指定创建进程的参数 Flag :: trace | log | {logfile, File} | statistics | debug
     start(GenMod, LinkP, Mod, Args, Options)
%% 相比start/6, 没有了执行name 的参数

start/6 会先确认给定的name 是否已经被使用, 如果被使用, 会返回

 {error, {already_started, Pid}} %% Pid 是名字为name 的进程

反之, 继续执行do_spawn , do_spawn 会调用proc_lib:spawn(_link) 函数创建进程, 并以 init_it 为初始化函数. (先挖个坑, ** proc_lib:spawn VS erlang:spawn ** 后面填)

注意, 此时已经有新的进程被创建了, 而 init_it 函数,已经是在由新的进程执行.

     init_it(GenMod, Starter, Parent, Mod, Args, Options)
Starter :: pid() %% 即调用proc_lib:spawn 的进程
Parent :: pid() | atom() %% Parent 只有在以link方式 start的时候才有意义 (此坑后填)
init_it(GenMod, Starter, Parent, Name, Mod, Args, Options)
%% Name 即指定的name, 首先会以Name 为参数调用 name_register/1 init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options) ->
GenMod:init_it(Starter, Parent, Name, Mod, Args, Options).
%% 回调 gen_server/gen_fsm 模块的init_it 函数

call/N

call/3 使用default_timeout 作为第四个参数调用 call/4 .

call/4 首先会进程一系列的参数校验, 然后调用do_call/4

     do_call(Process, Label, Request, Timeout) ->
%% 首先调用 bif monitor Process
try erlang:monitor(process, Process) of
Mref ->
%% 然后给 Process 发送消息
catch erlang:send(Process, {Label, {self(), Mref}, Request},
[noconnect]),
%% 并等待 Process 的返回结果, 就是在 handle_call 中的Reply 或者是 gen:reply 的 结果
receive
{Mref, Reply} ->
%% 关于 erlang:monitor/erlang:demonitor 的文档很详细
erlang:demonitor(Mref, [flush]),
{ok, Reply};
{'DOWN', Mref, _, _, noconnection} ->
Node = get_node(Process),
exit({nodedown, Node});
{'DOWN', Mref, _, _, Reason} ->
exit(Reason)
after Timeout ->
erlang:demonitor(Mref, [flush]),
exit(timeout)
end
catch
%% bif monitor Process 失败, 就 monitor Process 所在的 Node
error:_ ->
Node = get_node(Process),
monitor_node(Node, true),
receive
{nodedown, Node} ->
monitor_node(Node, false),
exit({nodedown, Node})
after 0 ->
Tag = make_ref(),
%% bif erlang:'!'/2 发送消息
Process ! {Label, {self(), Tag}, Request},
%% 等待响应
wait_resp(Node, Tag, Timeout)
end
end.

call/3 以及 call/4 主要就做了这些事情.

reply/2

此函数实现在erl 代码层面很简单, 但对gen_server 进程来说,有独特的作用,后续会进行分析.

填坑

proc_lib:spawn 和 erlang:spawn 的区别:

翻下代码,就能看到, so easy

相比较 erlang:spawn, proc_lib:spawn 在被创建的进程中,添加了一些信息:

'$ancestors',  '$initial_call'.

在某些场景下,这些信息对于定位进程的归属有很大的作用.比如说:定位僵死进程的归属,定位崩溃进程的归属等.

Erlang generic standard behaviours -- gen的更多相关文章

  1. Erlang generic standard behaviours -- gen_server system msg

    这是Erlang generic standard behaviors gen_server 分析的系列的最后一篇,主要分析gen_server module 辅助性的功能函数. 在gen_serve ...

  2. Erlang generic standard behaviours -- gen_server module

    在分析完gen module (http://www.cnblogs.com/--00/p/4271386.html)之后,就可以开始进入gen_server 的主体module 了.gen_serv ...

  3. Erlang generic standard behaviours -- summary

    gen_server 相关的片段分析得也差不多了, 这篇作为一个简要的总结.这一系列相关的分析暂且告一段落(之后如有必要,还会回来的 ^^ ),下一个系列主要是以pool 相关, 包括但不仅限于开源项 ...

  4. Erlang generic standard behaviours -- gen_server terminate

    gen_server 主体 module 已经分析完了(http://www.cnblogs.com/--00/p/4271982.html),接着,分析下gen_server 中的terminate ...

  5. Erlang generic standard behaviours -- gen_server hibernate

    hibernate 主要用于在内存空闲时,通过整理进程的stack,回收进程的heap 来达到回收内存节省资源的效果. hibernate 可用于OTP 进程以及普通进程, hibernate 的官方 ...

  6. Erlang generic standard behaviours -- gen_server noblock call

    在Erlang 系统中,经常需要gen_server 进程来处理共享性的数据,也就是总希望一个gen_server 进程来为多个普通进程提供某种通用性的服务,这也是gen_server 设计的初衷.但 ...

  7. jQ1.5源码注释以及解读RE

    jQ作为javascript的库( ▼-▼ ), 尽善尽美, 代码优美,  值得学习.  这一周平常上班没啥事也看jQ1.5的代码, 今天周六差不多看完了(Sizzle部分还没看), 重新看了一下, ...

  8. Java性能提示(全)

    http://www.onjava.com/pub/a/onjava/2001/05/30/optimization.htmlComparing the performance of LinkedLi ...

  9. PCB设计铜铂厚度、线宽和电流关系

    以下总结了网上八种电流与线宽的关系公式,表和计算公式,虽然各不相同(大体相近),但大家可以在实际的PCB板设计中,综合考虑PCB板的大小,通过电流,选择一个合适的线宽. 一.PCB电流与线宽 PCB载 ...

随机推荐

  1. EB(存储单位)

    abbr.艾字节,1EB=1024PB 计算机的存储单位 位 bit (比特)(Binary Digits):存放一位二进制数,即 0 或 1,最小的存储单位. 字节 byte:8个二进制位为一个字节 ...

  2. 运行时---关联Associated

    关联:指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分   一.在类的定义之外为类增加额外的存储空间        使用关联,我们可以不用修改类的定义而为其对象增加存储空间.这在我 ...

  3. 开源Cheops软件在企业中的应用

    笔者在所属分公司的网络改造的网络改造中采用了开源软件作为其网络管理软件,曾经使用时间达2年多,没有出现过问题,其本身具备的主要管理功能完全可以商业的网管软件相媲美,下文将其部署心得和大家一起分享.一. ...

  4. 开源项目:libbpg

    1 ubuntu下编译libbpg(编译机器64bit) 安装cmake,libpng,yasm,gcc,g++ cmake版本最低为2.8.8,安装完毕后使用cmake --version查看是否安 ...

  5. 在python3.5中使用pip

    我centos7上同时有python2.7和python3.5.现在希望能在使用python3.5时也能用pip.本来这应该是很容易的一件事,然而我一步步掉进坑里.. 官网安装pip的方法是,http ...

  6. Eclipse Egit 安装

    help->Install new software-> 在 work within 中输入以下网址 安装地址: http://download.eclipse.org/egit/upda ...

  7. leetcode 21

    合并两个有序数列.属于基础的数据结构问题,核心在于对链表的操作. 代码如下: /** * Definition for singly-linked list. * struct ListNode { ...

  8. Javascrpt

    HTML HTML概述: HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他 ...

  9. 1.异步消息Jms及其JmsTemplate的源代码分析,消息代理ActiveMQ

    一. 介绍 借助Spring,有多种异步消息的可选方案,本章使用Jms.Jms的消息模型有两种,点对点消息模型(队列实现)和发布-订阅消息模型(主题). 图1.点对点消息模型(一对一) 图2.发布-订 ...

  10. CentOS 6破解Mysql5.5的办法

    首先,你必须要有操作系统的root权限了.要是连系统的root权限都没有的话,先考虑root系统再走下面的步骤.类似于安全模式登录系统,有人建议说是pkill mysql,但是我不建议哈.因为当你执行 ...