应用 | 7. Applications
7项申请
本节将使用app(4)
和application(3)
内核中的手册页。
7.1应用概念
当您编写了实现某些特定功能的代码时,您可能希望将代码变成应用
,也就是可以作为一个单元启动和停止的组件,它也可以在其他系统中重用。
要做到这一点,请创建一个application callback module
,并描述如何启动和停止应用程序。
然后,应用规范
是必需的,它放在application resource file
.除其他外,此文件指定应用程序由哪些模块组成以及回调模块的名称。
如果你用systools
,用于打包代码%28的Erlang/OTP工具(参见Releases
%29,每个应用程序的代码都放在一个单独的目录中,该目录位于预定义的目录下。directory structure
...
7.2应用程序回调模块
如何启动和停止应用程序的代码,即监督树,由两个回调函数描述:
start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State}
stop(State)
start
在启动应用程序时调用,并通过启动最高主管创建监督树。它将返回最高主管的PID和一个可选的术语,State
,默认为[]
这个任期通过的方式是stop
...
StartType
通常是原子normal
它只有在接管或故障转移的情况下才具有其他价值,请参见Distributed Applications
...
StartArgs
是由键定义的。mod
在application resource file
...
stop/1
被称为后
应用程序已经停止,并将进行任何必要的清理。应用程序的实际停止,即监督树的关闭,将自动处理,如Starting and Stopping Applications
...
应用程序回调模块的示例,该模块用于从Supervisor Behaviour
*
-module(ch_app).
-behaviour(application).
-export([start/2, stop/1]).
start(_Type, _Args) ->
ch_sup:start_link().
stop(_State) ->
ok.
无法启动或停止的库应用程序不需要任何应用程序回调模块。
7.3应用资源文件
若要定义应用程序,请将应用规范
被创建,这将放在应用资源文件
,或者简单地说.app
档案:
{application, Application, [Opt1,...,OptN]}.
Application
,一个原子,是应用程序的名称。文件必须命名为Application.app
...
- 各
Opt
是元组{Key,Value}
定义应用程序的某个属性。所有的钥匙都是可选的。默认值用于任何省略的键。
最小值的内容.app
库应用程序的文件libapp
情况如下:
{application, libapp, []}.
最小值的内容.app
档案ch_app.app
对于监督树应用程序,如ch_app
情况如下:
{application, ch_app,
[{mod, {ch_app,[]}}]}.
钥匙mod
定义应用程序的回调模块和启动参数,在本例中ch_app
和[]
分别。这意味着在启动应用程序时将调用以下内容:
ch_app:start(normal, [])
当应用程序停止时,将调用以下内容。
ch_app:stop([])
使用时systools
,用于包装代码%28的Erlang/OTP工具--参见Releases
%29,钥匙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
-所有单元介绍
通过这个申请。systools
在生成引导脚本和tar文件时使用此列表。模块只能在一个应用程序中定义。默认为[]
...
registered
-申请中所有已登记程序的名称。systools
使用此列表检测应用程序之间的名称冲突。默认为[]
...
applications
-在启动此应用程序之前必须启动的所有应用程序。systools
使用此列表生成正确的引导脚本。默认为[]
请注意,所有应用程序至少都依赖于内核和STDLIB。
注
有关应用程序资源文件的语法和内容的详细信息,请参阅app
内核中的手册页。
7.4目录结构
当包装代码使用systools
,每个应用程序的代码都放在一个单独的目录中,lib/Application-Vsn
,在哪里Vsn
版本号。
知道这一点是有用的,即使systools
不使用,因为Erlang/OTP是按照OTP原则打包的,因此附带了特定的目录结构。代码服务器%28参见code(3)
内核%29中的手动页自动使用具有最高版本号的目录中的代码,如果存在一个应用程序的多个版本。
开发环境的目录结构指南
只要发布的目录结构符合description below
,但鼓励在开发环境中也使用相同的目录结构。应用程序目录名中应该省略版本号,因为这是发布步骤的工件。
一些子目录是所需
.一些子目录是任选
,这意味着只有当应用程序本身需要时才应该使用它。最后,一些子目录是推荐
,这意味着它被鼓励使用和使用如下所述。例如,鼓励文档和测试都存在于应用程序中,以便将其视为适当的OTP应用程序。
─ ${application}
├── doc
│ ├── internal
│ ├── examples
│ └── src
├── include
├── priv
├── src
│ └── ${application}.app.src
└── test
src
-必需。包含Erlang源代码,.app
文件和内部包含应用程序本身使用的文件。中的其他子目录src
可用作命名空间来组织源文件。这些目录不应超过一个级别。
priv
-任选。用于特定于应用程序的文件。
include
-任选。用于公共包括必须从其他应用程序访问的文件。
doc
-建议。任何源文档都应该放在这里的子目录中。
doc/internal
-建议。任何描述此应用程序的实现细节的文档(不打算发布)都应该放在这里。
doc/examples
-建议。关于如何使用此应用程序的示例的源代码应该放在这里。令人感到鼓舞的是,从该目录向公共文件提供了一些例子。
doc/src
-建议。文档的所有源文件,例如Markdown、AsciDoc或XML-文件,都应该放在这里。
test
-建议。所有关于测试的文件,例如测试套件和测试规范,都应该放在这里。
可能需要开发环境中的其他目录。如果使用的是Erlang以外语言的源代码,例如NIF的C代码,那么该代码应该放在一个单独的目录中。按照惯例,建议在这些目录前面加上语言名称,例如c_src
对C来说,java_src
适用于Java或go_src
的目录_src
后缀表示它是应用程序和编译步骤的一部分。最终的构建工件应该针对priv/lib
或priv/bin
目录。
大priv
目录保存应用程序在运行时需要的资产。可执行文件应驻留在priv/bin
而动态链接的库应该驻留在priv/lib
.其他资产可自由居住在priv
目录,但建议以结构化的方式这样做。
生成Erlang代码的其他语言(如ASN.1或MiB)的源文件应放在目录中、顶层或src
,使用与源语言相同的名称,例如asn1
和mibs
构建工件应该放在它们各自的语言目录中,例如src
用于Erlang代码或java_src
用于Java代码。
大.app
发布的文件可以驻留在ebin
-开发环境中的目录,但令人鼓舞的是,这是构建步骤的工件。根据公约a.app.src
文件,该文件驻留在src
目录。此文件与.app
文件,但在构建步骤中可以替换某些字段,例如应用程序版本。
目录名不应大写。
它被鼓励省略空目录。
发布系统的目录结构
发布的应用程序必须遵循一定的结构。
─ ${application}-${version}
├── bin
├── doc
│ ├── html
│ ├── man[1-9]
│ ├── pdf
│ ├── internal
│ └── examples
├── ebin
│ └── ${application}.app
├── include
├── priv
│ ├── lib
│ └── bin
└── src
src
-可选。包含Erlang源代码和应用程序本身使用的内部包含文件。在发布的应用程序中不再需要此目录。
ebin
-必需。包含Erlang对象代码,beam
档案。大.app
文件也必须放在这里。
priv
-任选。用于特定于应用程序的文件。code:priv_dir/1
用于访问此目录。
priv/lib
-建议。应用程序使用的任何共享对象文件,如nif或链接中的驱动程序,都应该放在这里。
priv/bin
-建议。应用程序使用的任何可执行文件,例如端口程序,都应该放在这里。
include
-任选。用于公共包括必须从其他应用程序访问的文件。
bin
-任选。任何作为应用程序产品的可执行文件,例如脚本或shell脚本,都应该放在这里。
doc
-任选。任何已发布的文档都应该放在这里的子目录中。
doc/man1
-推荐。申请可执行文件手册页。
doc/man3
-建议。模块API的手册页。
doc/man6
-推荐.应用程序概览手册页
doc/html
-任选。整个应用程序的HTML页面。
doc/pdf
-任选。PDF文档的整个应用程序。
大src
目录对于调试目的的发布可能很有用,但并不是必需的。大include
只有当应用程序具有公共包含文件时,目录才应该释放。
建议以这种方式发布的唯一文档是手册页。HTML和PDF通常会以其他方式分发。
它被鼓励省略空目录。
7.5应用控制器
当Erlang运行时系统启动时,许多进程将作为内核应用程序的一部分启动。其中一个过程是应用控制器
过程,登记为application_controller
...
应用程序上的所有操作都由应用程序控制器协调。它通过模块中的功能进行交互。application
,见application(3)
内核中的手册页。特别是,可以加载、卸载、启动和停止应用程序。
7.6装卸应用程序
在启动应用程序之前,它必须是装货
应用程序控制器从.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"}]
注
加载/卸载应用程序不会加载/卸载应用程序使用的代码。代码加载按照通常的方式进行。
7.7启动和停止应用程序
通过调用:
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
在模块中,并使用由mod
中的键.app
档案。
通过调用以下方法停止应用程序,但不卸载:
7> application:stop(ch_app).
ok
应用程序主程序通过告诉最高主管关闭应用程序来停止应用程序。最高主管告诉它的所有子进程关闭,等等;整个树以相反的开始顺序终止。然后,应用程序主程序调用应用程序回调函数。stop/1
在由mod
钥匙。
7.8配置应用程序
可以使用配置参数
这些是{Par,Val}
由键指定的元组env
在.app
档案:
{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
而erlang将使用命令行参数启动。-config Name
有关详情,请参阅config(4)
内核中的手册页。
例子:
档案test.config
创建具有以下内容:
[{ch_app, [{file, "testlog"}]}].
价值file
重写file
中定义的.app
档案:
% 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"}
如果release handling
,则将使用一个系统配置文件,并调用该文件。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"}
7.9应用程序启动类型
阿启动类型
在启动应用程序时定义:
application:start(Application, Type)
application:start(Application)
与呼叫相同application:start(Application, temporary)
.类型也可以是permanent
或transient
*
- 如果永久应用程序终止,则所有其他应用程序和运行时系统也将终止。
- 如果瞬态应用程序因原因而终止
normal
,这是报告,但没有其他应用程序被终止。如果一个临时应用程序异常终止,这是由于任何其他原因,而不是normal
,所有其他应用程序和运行时系统也将终止。
- 如果临时应用程序终止,则报告这一点,但没有终止其他应用程序。
应用程序始终可以通过调用application:stop/1
无论采用何种模式,其他应用程序都不会受到影响。
瞬态模式几乎没有实际用途,因为当监督树终止时,原因被设置为shutdown
,不是normal
...