应用 | 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是由键定义的。modapplication 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/libpriv/bin目录。

priv目录保存应用程序在运行时需要的资产。可执行文件应驻留在priv/bin而动态链接的库应该驻留在priv/lib.其他资产可自由居住在priv目录,但建议以结构化的方式这样做。

生成Erlang代码的其他语言(如ASN.1或MiB)的源文件应放在目录中、顶层或src,使用与源语言相同的名称,例如asn1mibs构建工件应该放在它们各自的语言目录中,例如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).类型也可以是permanenttransient*

  • 如果永久应用程序终止,则所有其他应用程序和运行时系统也将终止。

  • 如果瞬态应用程序因原因而终止normal,这是报告,但没有其他应用程序被终止。如果一个临时应用程序异常终止,这是由于任何其他原因,而不是normal,所有其他应用程序和运行时系统也将终止。

  • 如果临时应用程序终止,则报告这一点,但没有终止其他应用程序。

应用程序始终可以通过调用application:stop/1无论采用何种模式,其他应用程序都不会受到影响。

瞬态模式几乎没有实际用途,因为当监督树终止时,原因被设置为shutdown,不是normal...