7.应用
本章應與?app(4)?和?application(3)?。
應用的概念
當我們寫了實現特定功能的代碼之后,我們可能想將代碼轉成一個?應用?(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應用資源文件的語法和內容在?app(4)?中有詳細的描述。
目錄結構
當使用?systools?對代碼進行打包的時候,每個應用的代碼都放在單獨的目錄中?lib/Application-Vsn?,其中?Vsn?是版本號。
即便沒有用到?systools?,最好也要了解它,因為Erlang/OTP其自身是按照OTP原則進行打包的所以才有了這個目錄結構。如果存在一個應用的多個版本,那么代碼服務器(見?code(3)?)會自動使用來自目錄中版本號最高的代碼。
應用目錄結構當然也可以用于開發環境。版本號是可以忽略的。
應用目錄有以下子目錄:
- src
- ebin
- priv
- 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?。
轉載于:https://www.cnblogs.com/qingshuiyj/p/3996228.html
總結
- 上一篇: 2022-2028全球气动测试探针行业调
- 下一篇: java 点云数据处理_点云数据处理学习