http://hje.iteye.com/blog/1211734html
應用的概念¶
當咱們寫了實現特定功能的代碼以後,咱們可能想將代碼轉成一個 應用 (application),這是能夠做爲一個單元啓動和中止的組建,同時它也能夠在其餘系統中被重用。
咱們要建立一個 應用回調模塊 ,其中描述了該應用應該如何被啓動和中止。
而後,須要一個應用規格,它被放在一個 應用資源文件 。咱們還指定該應用由哪些模塊組成,以及各個回掉模塊的名字。
若是咱們使用 systools ——Erlang/OTP用於打包的代碼(參見 發佈 ),每一個應用的代碼均可以按照預約的 目錄結構 放在單獨的目錄中。
應用回調模塊¶
如何啓動和中止應用的代碼,即監督樹,由如下兩個回掉函數來描述:
start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State}
stop(State)
當要經過啓動頂層督程來建立監督樹的時候,會調用 start 。它要返回頂層督程的pid和一個選項值 State ,默認爲 []。這個值會原樣傳遞給 stop 。
StartType 一般是原子 normal 。只有在接管或故障轉移中才會有其餘值,參見 分佈式應用 。 StartArgs 由 應用資源文件 中的鍵 mod 來定義。
在應用被中止以後會調用 stop/1 來進行必須的清除工做。注意應用實際的中止過程,也就是監督樹的關閉,是按照 啓動和中止應用 中所描述的方式自動處理的。
如下是一個例子,未來自 督程 一章中的督程打包爲一個應用回調模塊:
-module(ch_app).
-behaviour(application).
-export([start/2, stop/1]).
start(_Type, _Args) ->
ch_sup:start_link().
stop(_State) ->
ok.
一個庫應用——不能被啓動或者中止——則無須任何應用回調模塊。
應用資源文件¶
咱們經過建立一個放在應用資源文件——簡稱 .app 文件——中的應用規格來定義一個應用:
{application, Application, [Opt1,...,OptN]}.
Application 是一個表明應用的名稱的原子。文件必須被命名成 Application.app 。
每個 Opt 都是一個定義了應用某種特性的元組 {Key, Value} 。全部的鍵都是可選。忽略的鍵會使用默認的值。
例如,用於庫應用 libapp 的最小化的 .app 文件的內容爲:
{application, libapp, []}.
對於像 ch_app 這樣的監督樹應用的最小化 .app 文件的內容爲:
{application, ch_app,
[{mod, {ch_app,[]}}]}.
鍵 mod 定義了回調模塊以及應用的啓動參數,在這個例子中相應是 ch_app 和 []。這表示應用啓動的時候會調用:
ch_app:start(normal, [])
而當應用被中止的時候會調用:
ch_app:stop([])
當使用 systools 時,Erlang/OTP工具的打包代碼(參見 發佈 ),鍵 description、vsn、modules、registered 和 applications 則應該指定爲:
{application, ch_app,
[{description, "Channel allocator"},
{vsn, "1"},
{modules, [ch_app, ch_sup, ch3]},
{registered, [ch3]},
{applications, [kernel, stdlib, sasl]},
{mod, {ch_app,[]}}
]}.
description
簡短描述,字符串。默認爲 「」。
vsn
版本號,字符串。默認爲」「。
modules
由該應用引入的全部模塊。當生成啓動腳本和tar文件時, systools 將用到這個列表。一個模塊必須被定義於且僅於一個應用。默認爲[]。
registered
應用中全部註冊進程的名稱。 systools 使用這個列表來探測在應用之間是否有名稱衝突。默認爲 []。
applications
全部在此應用以前必須啓動的應用。 systools 使用該列表來生成正確的啓動腳本。默認爲 [],可是注意任何應用都要至少依賴於 kernel 和 stdlib 。
應用資源文件的語法和內容在 app(4) 中有詳細的描述。
目錄結構¶
當使用 systools 對代碼進行打包的時候,每一個應用的代碼都放在單獨的目錄中 lib/Application-Vsn ,其中 Vsn 是版本號。
即使沒有用到 systools ,最好也要了解它,由於Erlang/OTP其自身是按照OTP原則進行打包的因此纔有了這個目錄結構。若是存在一個應用的多個版本,那麼代碼服務器(見 code(3) )會自動使用來自目錄中版本號最高的代碼。
應用目錄結構固然也能夠用於開發環境。版本號是能夠忽略的。
應用目錄有如下子目錄:
•src
•ebin
•priv
•include
src
包含Erlang源代碼
ebin
包含Erlang目標代碼—— beam 文件。 .app 文件也放在這裏。
priv
用於應用專屬文件。例如,C執行程序就放在這裏。應該使用函數 code:priv_dir/1 來訪問這個目錄。
include
用於包含文件。
應用控制器¶
當啓動了Erlang運行時系統,做爲Kernel應用的一些進程會被啓動。其中一個進程是應用控制器進程,註冊爲 application_controller 。
全部對應用的操做都由應用控制器來協調。它經過模塊 application 裏的函數來暴露接口, 請參考 application(3) 。尤爲要了解,應用能夠被加載、卸載、啓動和中止。
加載和卸載應用¶
在能啓動一個應用以前,首先它必須被加載。應用控制器會讀取在 .app 中的信息並存起來。
1> application:load(ch_app).
ok
2> application:loaded_applications().
[{kernel,"ERTS CXC 138 10","2.8.1.3"},
{stdlib,"ERTS CXC 138 10","1.11.4.3"},
{ch_app,"Channel allocator","1"}]被中止的或者從未啓動過的應用,能夠被卸載。該應用相關的信息會從應用控制器的內部數據庫中刪除。
3> application:unload(ch_app).
ok
4> application:loaded_applications().
[{kernel,"ERTS CXC 138 10","2.8.1.3"},
{stdlib,"ERTS CXC 138 10","1.11.4.3"}]Note:
加載/卸載應用並不會加載/卸載該應用所使用的代碼。代碼加載是按照通常的方式進行的。
啓動和中止應用¶
啓動應用要調用:
5> application:start(ch_app).
ok
6> application:which_applications().
[{kernel,"ERTS CXC 138 10","2.8.1.3"},
{stdlib,"ERTS CXC 138 10","1.11.4.3"},
{ch_app,"Channel allocator","1"}]若是應用還沒有被加載,那麼應用控制器會首先使用 application:load/1 加載它。它會檢查 applications 鍵對應的值,來確保要在該應用運行以前啓動的應用都啓動了。
而後應用控制器爲應用建立一個應用主程序。它是該應用中全部進程的隊長。應用主程序經過調用應用模塊中的回調函數 start/2 啓動應用(會給出由在 .app 文件中的 mod 建定義的啓動參數)。
中止一個應用,但不卸載,可調用:
7> application:stop(ch_app).
ok
配置應用¶
可使用配置參數來對應用進行配置。它們在 .app 文件中是一個由鍵 env 指定的 {Par, Val} 元組列表。
{application, ch_app,
[{description, "Channel allocator"},
{vsn, "1"},
{modules, [ch_app, ch_sup, ch3]},
{registered, [ch3]},
{applications, [kernel, stdlib, sasl]},
{mod, {ch_app,[]}},
{env, [{file, "/usr/local/log"}]}
]}.
Par 必須是一個原子, Val 能夠是任意值。應用能夠經過調用 application:get_env(App, Par) 或一些其餘相似函數來獲取配置參數的值,參見 application(3) 。
例如:
% erl
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]
Eshell V5.2.3.6 (abort with ^G)
1> application:start(ch_app).
ok
2> application:get_env(ch_app, file).
{ok,"/usr/local/log"}.app 文件中的值能夠被系統配置文件中的值所覆蓋。系統配置文件是一個包含相關應用的配置參數的文件。
[{Application1, [{Par11,Val11},...]},
...,
{ApplicationN, [{ParN1,ValN1},...]}].
系統配置要被命名爲 Name.config 而且要使用命令行參數 -config Name 來啓動Erlang。更多信息參見 config(4) 。
例如:建立一個文件 test.config 包含一下內容:
[{ch_app, [{file, "testlog"}]}].
file 的值將覆蓋在 .app 文件中所定義的 file 的值:
% erl -config test
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]
Eshell V5.2.3.6 (abort with ^G)
1> application:start(ch_app).
ok
2> application:get_env(ch_app, file).
{ok,"testlog"}若是使用了 發佈處理 ,那麼只能使用一個系統配置文件同時該文件必須叫作 sys.config 。
在 .app 文件中的值,也包括系統配置文件中的值,均可以直接在命令行中被覆蓋:
% erl -ApplName Par1 Val1 ... ParN ValN例如:
% erl -ch_app file '"testlog"'
Erlang (BEAM) emulator version 5.2.3.6 [hipe] [threads:0]
Eshell V5.2.3.6 (abort with ^G)
1> application:start(ch_app).
ok
2> application:get_env(ch_app, file).
{ok,"testlog"}應用啓動類型¶
當啓動應用的時候要定義一個啓動類型。
application:start(Application, Type)
application:start(Application) 和調用 application:start(Application, temporary) 是同樣的。類型還能夠是 permanent 持久的或者 transient 過渡的:
•若是一個持久應用終止了,全部其餘的應用以及運行時系統都會被終止。
•若是一個過渡應用以 normal 理由終止了,那麼這個信息會被上報可是不會終止其餘應用。若是一個過渡應用異常終止了——即以非 normal 的理由終止了——那麼其餘應用以及運行時環境也會被終止。
•若是一個臨時(temporary)應用終止了,那麼會報告該信息但不會終止其餘應用。
咱們老是能夠經過明確調用 application:stop/1 來中止一個應用。不管是什麼模式,都不會影響其餘應用。
注意在實踐中不多使用過渡模式,由於當一個監督樹終止了,退出理由會被設置爲 shutdown ,而非 normal 。
http://erlang.shiningray.cn/otp-design-principles/applications.htmlshell