查看源代码 包含的应用程序
简介
一个应用程序可以包含其他应用程序。一个包含的应用程序有它自己的应用程序目录和 .app
文件,但是它是作为另一个应用程序的监督树的一部分启动的。
一个应用程序只能被另一个应用程序包含。
一个包含的应用程序可以包含其他应用程序。
一个不被任何其他应用程序包含的应用程序被称为主应用程序。
---
title: Primary Application and Included Applications
---
flowchart TD
prim_app((Primary Application))
subgraph Included Applications
app1((App))
app2((App))
app3((App))
app4((App))
app5((App))
subgraph Included Applications
app11((App))
end
subgraph Included Applications
app31((App))
app32((App))
end
end
prim_app --- app1 --- app11
prim_app --- app2
prim_app --- app3
prim_app --- app4
prim_app --- app5
app3 --- app31
app3 --- app32
应用程序控制器在加载主应用程序时会自动加载任何包含的应用程序,但不会启动它们。相反,包含的应用程序的顶层监督者必须由包含应用程序中的一个监督者启动。
这意味着在运行时,一个包含的应用程序实际上是主应用程序的一部分,并且包含的应用程序中的一个进程认为它自己属于主应用程序。
指定包含的应用程序
要包含哪些应用程序由 .app
文件中的 included_applications
键定义
{application, prim_app,
[{description, "Tree application"},
{vsn, "1"},
{modules, [prim_app_cb, prim_app_sup, prim_app_server]},
{registered, [prim_app_server]},
{included_applications, [incl_app]},
{applications, [kernel, stdlib, sasl]},
{mod, {prim_app_cb,[]}},
{env, [{file, "/usr/local/log"}]}
]}.
启动期间同步进程
包含的应用程序的监督树是作为包含应用程序的监督树的一部分启动的。如果包含和被包含的应用程序中的进程之间需要同步,可以通过使用启动阶段来实现。
启动阶段由 .app
文件中的 start_phases
键定义,格式为元组列表 {Phase,PhaseArgs}
,其中 Phase
是一个原子,PhaseArgs
是一个项。
包含应用程序的 mod
键的值必须设置为 {application_starter,[Module,StartArgs]}
,其中 Module
照常是应用程序回调模块。StartArgs
是作为参数提供给回调函数 Module:start/2
的一个项。
{application, prim_app,
[{description, "Tree application"},
{vsn, "1"},
{modules, [prim_app_cb, prim_app_sup, prim_app_server]},
{registered, [prim_app_server]},
{included_applications, [incl_app]},
{start_phases, [{init,[]}, {go,[]}]},
{applications, [kernel, stdlib, sasl]},
{mod, {application_starter,[prim_app_cb,[]]}},
{env, [{file, "/usr/local/log"}]}
]}.
{application, incl_app,
[{description, "Included application"},
{vsn, "1"},
{modules, [incl_app_cb, incl_app_sup, incl_app_server]},
{registered, []},
{start_phases, [{go,[]}]},
{applications, [kernel, stdlib, sasl]},
{mod, {incl_app_cb,[]}}
]}.
当启动一个包含应用程序的主应用程序时,主应用程序以正常方式启动,即
- 应用程序控制器为该应用程序创建一个应用程序主控
- 应用程序主控调用
Module:start(normal, StartArgs)
来启动顶层监督者。
然后,对于主应用程序和每个包含的应用程序,按照从上到下、从左到右的顺序,应用程序主控会为每个为主应用程序定义的阶段调用 Module:start_phase(Phase, Type, PhaseArgs)
,按照该顺序。如果一个阶段没有为包含的应用程序定义,则不会为该阶段和应用程序调用该函数。
以下要求适用于包含的应用程序的 .app
文件
- 必须包含
{mod, {Module,StartArgs}}
选项。此选项用于查找应用程序的回调模块Module
。StartArgs
被忽略,因为Module:start/2
仅针对主应用程序调用。 - 如果包含的应用程序本身包含其他应用程序,则必须包含
{mod, {application_starter, [Module,StartArgs]}}
选项。 - 必须包含
{start_phases, [{Phase,PhaseArgs}]}
选项,并且指定阶段的集合必须是为主应用程序指定的阶段集合的子集。
当启动如上定义的 prim_app
时,应用程序控制器在 application:start(prim_app)
返回值之前调用以下回调函数
application:start(prim_app)
=> prim_app_cb:start(normal, [])
=> prim_app_cb:start_phase(init, normal, [])
=> prim_app_cb:start_phase(go, normal, [])
=> incl_app_cb:start_phase(go, normal, [])
ok