注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Code@Pig Home

喜欢背着一袋Code傻笑的Pig .. 忧美.欢笑.记忆.忘却 .之. 角落

 
 
 

日志

 
 

[每日一Errr~lang] OTP (2) -- application  

2010-03-06 19:15:09|  分类: lang_erlang |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
这期节目将为大家奉上,如何将你的 erlang 程序用于生产环境,发布一个 application。hohoho~,是不是很期待。
http://www.erlang.org/doc/design_principles/applications.html

module 加载路径
erl vm 运行时,我们加载一个模块的过程,其实是 erlang 会搜索一些路径,尝试加载此模块。这些路径称为 code path。如下,我们就可以加载 ./ebin 中的模块了。
-------------------------------------------
1> code:get_path().
[".","/usr/local/lib/erlang/lib/kernel-2.13.5/ebin",
 "/usr/local/lib/erlang/lib/stdlib-1.16.5/ebin",
2> code:add_patha("./ebin").
true
3> code:get_path().
["./ebin",".",
 "/usr/local/lib/erlang/lib/kernel-2.13.5/ebin",
 "/usr/local/lib/erlang/lib/stdlib-1.16.5/ebin",
-------------------------------------------
其中 add_path 有好几个版本,add_patha() 表示将路径加入 path list 的最前面。

再来看一个完整项目的目录结构:
myapp/
     + ebin/                                                  编译后的 .beam 文件
     + src/                                                    源文件 .erl
           + myapp_worker.erl                         业务逻辑模块
     + Makefile
     + start.sh
-------------------------------------------
%% src/myapp_worker.erl
-module(myapp_worker).
-behaviour(gen_server).

-export([init/1, handle_call/3, terminate/2, code_change/3]).
-export([start_link/0, foo/1]).

start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
foo(Val) -> gen_server:call(?MODULE, {foo, Val}).


init(_Args) ->
    {ok, []}.

handle_call({foo, Val}, _From, State) ->
    io:format("foo = ~p~n", [Val]),
    {reply, ok, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
-------------------------------------------
# Makefile
all:
        erlc -W -o ./ebin src/*.erl
-------------------------------------------
# start.sh
exec erl -pa $PWD/ebin
-------------------------------------------
$ make
erlc -W -o ./ebin src/*.erl
src/myapp_worker.erl:2: Warning: undefined callback function handle_cast/2 (behaviour 'gen_server')
src/myapp_worker.erl:2: Warning: undefined callback function handle_info/2 (behaviour 'gen_server')
$ sh start.sh
Erlang R13B04 (erts-5.7.5) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.7.5  (abort with ^G)
1> myapp_worker:start_link().
{ok,<0.37.0>}
2> myapp_worker:foo(hello).
foo = hello
ok
-------------------------------------------
因为 start.sh 里,启动 erl vm 时,通过 -pa 添加了 ./ebin 路径,所以我们可以直接调用模块 myapp_worker 的函数。


启用 application 框架
预热内容结束,开始说正题啦。对于一个完整的应用,肯定是由多个 module 组成。erl 可让你把这些 module 打包成 application,同时加载,同时卸载。我们来更新上面的目录结构:
myapp/
     + ebin/                                                  编译后的 .beam 文件
     + src/                                                    源文件 .erl
           + myapp.app                                   资源文件
           + myapp_app.erl                              application 启动 module
           + myapp_worker.erl                         业务逻辑模块
     + Makefile
     + start.sh
-------------------------------------------
# Makefile
all:
        erlc -W -o ./ebin src/*.erl
        cp ./src/myapp.app ./ebin/
-------------------------------------------
%% src/myapp_app.erl
-module(myapp_app).
-behaviour(application).

-export([start/2, stop/1]).

start(_Type, _Args) ->
    myapp_worker:start_link().

stop(_State) ->
    ok.
-------------------------------------------
$ cat src/myapp.app
{application, myapp,
    [{description, "myapp test"},
     {vsn, "1"},
     {modules, [myapp_app, myapp_worker]},
     {registered, [myapp_worker]},
     {applications, [kernel, stdlib]},
     {mod, {myapp_app, []}}
    ]}.
-------------------------------------------
$ make
erlc -W -o ./ebin src/*.erl
cp ./src/myapp.app ./ebin/
$ sh start.sh
1> application:load(myapp).
ok
2> application:start(myapp).
ok
3> myapp_worker:foo(hello).
foo = hello
ok
4> application:stop(myapp).

=INFO REPORT==== 7-Mar-2010::10:14:32 ===
    application: myapp
    exited: stopped
    type: temporary
ok
5> whereis(myapp_worker).
undefined
6> application:unload(myapp).
ok
-------------------------------------------
其中,myapp.app 定义了此 application 的一些行为,比如:{modules, [myapp_app, myapp_worker]},决定了 myapp 加载时,必须存在的一些模块。
application:load(myapp) 会根据 myapp.app 中的定义,把一些准备工作完成。而 application:start(myapp) 则通过 {mod, {myapp_app, []}} 的定义,调用 myapp_app:start(Type, Args) 来启动整个 myapp。
关于 application 的一些细节,可以参考:http://www.erlang.org/doc/design_principles/applications.html


Final!让 application 自动启动
最后,我们来让 myapp 在 erl vm 启动时,也自动启动。
myapp/
     + ebin/                                                  编译后的 .beam 文件
           + myapp.app                                   资源文件
     + src/                                                    源文件 .erl
           + myapp.erl                                     erl vm 启动执行的 module
           + myapp_app.erl                              application 启动 module
           + myapp_worker.erl                         业务逻辑模块
     + Makefile
     + start.sh
-------------------------------------------
$ cat src/myapp.erl
-module(myapp).
-export([start/0, stop/0]).

start() ->
    application:start(myapp).

stop() ->
    application:stop(myapp).
-------------------------------------------
$ cat start.sh
exec erl -pa $PWD/ebin -s myapp
-------------------------------------------
$ sh start.sh
1> myapp_worker:foo(hello).
foo = hello
ok
-------------------------------------------
通过 -s 指令,让 erl 启动时执行 myapp:start(),来自动启动 application myapp。

哦哈哈~,一个完成的 appliation 就这样完成啦。本期节目也顺利结束,欢迎下次收看。
  评论这张
 
阅读(885)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017