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的设计目的是通过运行一个或者多个进程来完成一定功能.为了能够管理这些进程的生命周期,需要通过supervisor进行管理.

application:start(log4erl).实际上是执行了application:start(log4erl,temporary).第二个参数表示应用程序的启动类型(Start_Type).启动类型还可以是permanent  transient,三种启动类型的区别是:如果Start_Type==permanent 应用程序终止之后所有其它的应用程序和运行时系统都会死掉;如果Start_Type==transient 应用程序终止的原因是normal,这个消息会报出来但是其它应用程序不会重启,如果应用程序终止的原因不是normal,其他应用程序和运行时也会跟着死掉;如果Start_Type==temporary 应用程序死掉会报错误出来但是其它应用程序不受影响.注意实践过程中很少使用transient参数,因为进程树崩掉的时候,进程正常退出原因是shutdown不是normal,这个我之前的文章提到过:[Erlang 0017]Erlang/OTP基础模块 proc_lib 无论使用哪种类型启动,直接调用stop方法关闭application是不会影响到其它应用程序的.

之前遇到过一个比较严重的问题导致应用崩掉,当时就有同事问为什么erlang的进程还在,或者说运行时还活着?其实就是因为我们启动应用程序的时候默认使用了temporary;

application配置文件
   application的配置文件(Application Resource File)基本上确定了application的格局.如果启动失败了就要检查一下配置文件了,配置文件命名要求必须与application命名一致,即必须要有一个log4erl.app文件:

{application, log4erl,
[{description, "Logger for erlang in the spirit of Log4J"},
{vsn, "0.9.0"},
{modules, [console_appender, %%该配置节可以留空 []
dummy_appender,
email_msg,
error_logger_log4erl_h,
% ................省略部分模块
xml_appender]},
{registered,[log4erl]}, %%这个应用程序将使用的注册名
{applications, [kernel,stdlib]}, %%注意这个配置节是指定当前应用程序依赖哪些应用程序,类似Windows服务的依赖关系
{mod, {log4erl,[]}},
%{env,[{key,value},{k2,v2}]}, %env配置节,里面以key-value的形式组织配置数据.可以用application:get_env/2读取.
{start_phases, []}
]}.
 
 

application启动过程

Erlang运行时启动时,application controller进程会随着Kernel应用程序启动,在erlang shell中可以通过whereis(application_controller)找到它.应用程序相关的操作都由它来协调完成,它通过application模块暴露出来的接口来实现应用程序的加载,卸载,启动,停止等等.

应用程序启动之前首先会进行加载load,如果没有没有加载application controller会首先执行load/1.加载完成猴子偶application controller会检查application配置文件中的applications配置节中所列出的应用程序都已经在运行.如果有依赖项还没有启动,就抛出{error,{not_started,App}}的错误.

完成依赖项检查之后application controller会为application创建application master.application master会成为该application中所有进程的Group Leader.(group leader决定了输出重定向的位置,参见这个问题:如何从A节点调用B节点的一个函数,结果输出到B节点呢?) .通过配置文件的mod配置节,application master知道要调用回调函数log4erl:start/2.

application behavior有两个回调函数需要实现 start/2 stop/1分别来指定应用程序如何启动,如何停止.启动application的时候调用start方法通过启动顶层的supervisor来创建进程树.log4erl实现了application的behavior,它的start方法也是中规中矩的启动了顶层superior:

 
start(_Type, []) ->
    log4erl_sup:start_link(?DEFAULT_LOGGER). %%这里?DEFAULT_LOGGER宏的值为default_logger

start对返回值是有规格要求的:start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State}

当返回结果不一致的时候应用程序自然启动失败,初学的时候最常见的错误就是加一下输出看看是不是启动了,结果就悲剧了.比如下面的代码,start函数的返回值是最后一个表达式io:format的值,而这个结果是ok,不符合application对start回调函数结果的要求.

start(Startype,Arg) ->
    demo_sup:start_link(),
    io:format("demo app start").

application停止过程

要停止application,application master首先会调用Module:prep_stop/1(如果存在),然后告知顶层的supervisor关闭(shutdown),shutdown的过程:整个监控树的所有进程和包含的应用程序按照启动的逆序终止.shutdown完成之后,application master调用Module:stop/1.最后application master自己终止掉.application停止了,但是依然处于已加载的状态(loaded).

%log4erl stop
stop(_State) ->
    log_filter_codegen:reset(),
    ok.

 

启动 appmon:start()获得更为直观的印象.下面是log4erl应用程序进程的组织方式,log4erl_sup是log4erl application的顶层supervisor,上面的<0.42.0>和<0.43.0>按照上文的介绍应该是application master进程,我们通过取进程信息来验证:

 

 
4> erlang:process_info(pid(0,42,0)).
[{current_function,{application_master,main_loop,2}},
{initial_call,{proc_lib,init_p,5}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[<0.6.0>,<0.43.0>]},
{dictionary,[{'$ancestors',[<0.41.0>]},
              {'$initial_call',{application_master,init,4}}]},
{trap_exit,true},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.42.0>},
{total_heap_size,233},
{heap_size,233},
{stack_size,6},
{reductions,23},
{garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,65535},
                      {minor_gcs,0}]},
{suspending,[]}]
5> erlang:process_info(pid(0,43,0)).
[{current_function,{application_master,loop_it,4}},
{initial_call,{application_master,start_it,4}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[<0.42.0>,<0.44.0>]},
{dictionary,[]},
{trap_exit,true},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.42.0>},
{total_heap_size,233},
{heap_size,233},
{stack_size,5},
{reductions,65},
{garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,65535},
                      {minor_gcs,0}]},
{suspending,[]}]
 
6> application:stop(log4erl).
ok

=INFO REPORT==== 27-Dec-2011::20:29:47 ===
    application: log4erl
    exited: stopped
    type: temporary
7> erlang:process_info(pid(0,43,0)).
undefined
8> erlang:process_info(pid(0,42,0)).
undefined
9>

 
今天先到这里,晚安!
 
 

理解Erlang/OTP - Application的更多相关文章

  1. 理解Erlang/OTP Supervisor

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

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

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

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

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

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

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

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

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

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

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

  7. Erlang/OTP 中文手册

    http://erldoc.com/ Open Telecom Platform application array asn1rt base64 binary calendar code dbg di ...

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

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

  9. CentOS 6.5安装Erlang/OTP 17.0

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

随机推荐

  1. theme-windowAnimationStyle 动画设置

    对于windowAnimationStyle 的引用,目前自己发现的有两处 1.就是直接在Theme 中引用的,如下 <style name="Theme.Funui" pa ...

  2. JS/CSS 全屏幕导航 – 从上到下动画

    <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...

  3. QQ群功能设计与心理学

    刚刚在一个Java技术交流群,发了个 "博客投票"的广告. 群主两眼一黑,瞬间就把我给干掉了. 看到QQ给出的系统消息,发现QQ群的一个功能做得很不错. 大家注意到,右边有个&qu ...

  4. 不在JPA 的 persistence.xml 文件中配置Entity class的解决办法

    在Spring 集成 Hibernate 的JPA方式中,需要在persistence配置文件中定义每一个实体类,这样非常地不方便,2种方法可以解决此问题: 这2种方式都可以实现不用在persiste ...

  5. C++组合数(combination)的实现

    实现: (nm) 既需要计算组合的总数 (32)=3: 也需要分别获得每一种组合的情形,用于穷举搜索: 1, 2; 1, 3; 2, 3 1. 递归实现 // picked + toPick == m ...

  6. Java基础学习总结(49)——Excel导入导出工具类

    在项目的pom文件中引入 <dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifac ...

  7. [D3] Create DOM Elements with D3 v4

    Change is good, but creating from scratch is even better. This lesson shows you how to create DOM el ...

  8. java程序猿经常使用的工具名称--知道中文意思吗

    在学习java的时候常常会碰到一些单词,可是一般的时候也不是非常在意这个单词的意思,而是能够了解到这个工具或者框架能够做什么就能够了.偶尔总结了一下还蛮有意思的.例如以下, 假设有遗漏,各位能够帮忙补 ...

  9. 装饰模式和python装饰器

    装饰器和装饰模式 先给出两者的定义: - 装饰器:装饰器是一个非常著名的设计模式,常常被用于有切面需求的场景.较为经典的有插入日志.性能測试.事务处理等. 装饰器是解决这类问题的绝佳设计.有了装饰器, ...

  10. C语言结构体的字节对齐原则

    为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...