demo
|-doc
|-ebin
|-include
|-src
说明:
(1) demo, 这是应用的名称, 也是项目的根目录.
(2) doc, 用于存放文档, 可选.
(3) ebin, 用户存放编译后的可执行文件(.beam), demo.app 元数据文件(application resource file)也存放于该目录下。
(4) src, 顾名思义, 用于存放源代码.
第二步,构造.app文件, demo.app内容如下.
{application, %(1)
demo, %(2)
[ %(3)
{description, "this is a test erlang project"},
{vsn, "0.1.0"},
{modules, [demo_app,
demo_sup,
demo_server]},
{registered, [demo_sup]},
{applications, [kernel, stdlib]},
{mod, {demo_app, []}}]
}.
(1) application, 元组第一项
(2) AppName, 即 demo, 应用的名称
(3) [Options], 这是一个参数列表, 每个成员都是一个{key, Value}的结构.
第三步,构造一个应用行为模式demo.erl
每个应用都要实现一个application行为(behaviour)的回调模块,它的作用有, 1 提供相应的start, stop接口,控制应用的启动停止, 2 负责启动应用的根监督者(root supervisour), 根监督者是应用中其它进程的鼻祖.
下面是文件demo.erl的内容.
%%
%% flagcugb@126.com
%%
-module(demo_app).
-behaviour(application).
-export([
start/2,
stop/1
]).
start(_Type, _StartArgs) ->
case demo_sup:start_link() of
{ok, Pid} ->
{ok, Pid};
Error ->
Error
end.
stop(_State) ->
ok.
第四步, 构造根监督者模块 demo_sup.erl
应用是一棵由监督者和工作进程共同构成的进程树, 树根就是根监督者, 它的作用就是管理它的子进程, 如启动, 停止, 重启等.
-module(demo_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
-define(SERVER, ?MODULE).
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
init([]) ->
Server = {demo_server, {demo_server, start_link, []},
permanent, 2000, worker, [demo_server]},
Children = [Server],
RestartSdemoategy = {one_for_one, 0, 1},
{ok, {RestartSdemoategy, Children}}.
第五步, 实现工作者模块 demo_server.erl用 gen_server 来实现一个简单的工作者.
%%% -------------------------------------------------------------------
%%% Author : flagcugb@126.com
%%% Description : 每秒钟打印一个 Tic 信息
%%%
%%% -------------------------------------------------------------------
-module(demo_server).
-behaviour(gen_server).
-export([start_link/0, stop/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-record(state, {}).
-define(LOOP_TIME, 1000).
%% @doc 启动一个gen_server
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
stop() ->
ok.
init([]) ->
ok = start_tic_timer(),
erlang:send_after(?LOOP_TIME, self(), {'tic'}),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info({'tic'}, State) ->
ok = do_tic(),
ok = start_tic_timer(),
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Exdemoa) ->
{ok, State}.
%%-------------
%% internal API
%%-------------
do_tic() ->
io:format("* Tic ~p~n", [calendar:local_time()]),
ok.
start_tic_timer() ->
erlang:send_after(?LOOP_TIME, self(), {'tic'}),
ok.
第六步, 编译两种方法:
(1) 直接编译
erlc -o ebin src/*.erl
(2) 借助makefile, 方便以后扩展, makefile内容如下
.PHONY:all clean all: erlc -o ebin src/*.erl clean: @echo "cleaning ... ..." -rm ebin/*.beam @echo "ok"
第七步, 启动
erl -pa ebin>application:start(demo).