檢視原始碼 包含的應用程式

簡介

一個應用程式可以包含其他應用程式。一個包含的應用程式有自己的應用程式目錄和 .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}} 選項。此選項用於尋找應用程式的回呼模組 ModuleStartArgs 會被忽略,因為 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