- application:start(ejabberd).
application用來表示一個可以單獨啟動和停止、并被復用的程序單元。通常一個application都有一個同名的app文件來定義。
對于系統(tǒng)工具(systool)直接調用的app文件必須包含以下幾項:
description, vsn, modules, registered, applications
我們查看ejabberd.app可以看到以下內容:
- {application, ejabberd,
- [{description, "ejabberd"},
- {vsn, "2.1.7"},
- {modules, [acl,
- ......
- {registered, [ejabberd,
- ......
- {applications, [kernel, stdlib]},
- {env, []},
- {mod, {ejabberd_app, []}}]}.
最后一項:mod 定義了應用程序的回調模塊和啟動參數(shù)。 在應用程序啟動時會由主導進程來調用這個模塊的start/2方法。
ejabberd_app.erl 中的start/2 :
- start(normal, _Args) ->
- ejabberd_loglevel:set(4),
- write_pid_file(),
- application:start(sasl),
- randoms:start(),
- db_init(),
- sha:start(),
- stringprep_sup:start_link(),
- xml:start(),
- start(),
- translate:start(),
- acl:start(),
- ejabberd_ctl:init(),
- ejabberd_commands:init(),
- ejabberd_admin:start(),
- gen_mod:start(),
- ejabberd_config:start(),
- ejabberd_check:config(),
- connect_nodes(),
- %% Loading ASN.1 driver explicitly to avoid races in LDAP
- catch asn1rt:load_driver(),
- Sup = ejabberd_sup:start_link(),
- ejabberd_rdbms:start(),
- ejabberd_auth:start(),
- cyrsasl:start(),
- % Profiling
- %ejabberd_debug:eprof_start(),
- %ejabberd_debug:fprof_start(),
- maybe_add_nameservers(),
- start_modules(),
- ejabberd_listener:start_listeners(),
- INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]),
- Sup;
我們可以看到它調用了一系列的方法和函數(shù)來完成整個應用的啟動。
- 1. ejabberd_loglevel:set(4) //設置日志級別
- 2. write_pid_file() //將當前進程標識寫到環(huán)境變量EJABBERD_PID_PATH定義的文件中
- 3. application:start(sasl) //啟動sasl應用 ,具體sasl應用所提供的服務請查看<a >sasl</a>
- 4. randoms:start() //注冊一個名為random_generator,用當前時間做種子生成隨機字符串的進程
- 5. db_init() //初始化并啟動本地的mnesia數(shù)據(jù)庫,并等待直到所有表可用或超時
- 7. stringprep_sup:start_link() //啟動一個監(jiān)控進程
- 8. xml:start() //提供xml處理功能
- 9. start() //注冊進程自身為ejabberd,設置日志目錄,加載驅動
- 10. translate:start()//從環(huán)境變量EJABBERD_MSGS_PATH定義的位置找*.msg 并加載到ets:translations 表中(國際化)
- 12. ejabberd_ctl:init() //創(chuàng)建兩張表ejabberd_ctl_cmds,ejabberd_ctl_host_cmd
- 13. ejabberd_commands:init() //創(chuàng)建表ejabberd_commands
- 14. ejabberd_admin:start() //注冊常用的ejabberd_command到表ejabberd_commands
這里的ejabberd_command類似于java中的虛方法,這個ejabberd_command 具有指定的名稱、指定類型數(shù)量參數(shù)、指定類型返回值。
例如:
#ejabberd_commands{name = register, tags = [accounts],
desc = "Register a user",
module = ?MODULE, function = register,
args = [{user, string}, {host, string}, {password, string}],
result = {res, restuple}},
定義了一個名為register,接受[{user, string}, {host, string}, {password, string}] 參數(shù),返回{res, restuple}的虛方法。
- 15. gen_mod:start() //創(chuàng)建表ejabberd_modules
- 16. ejabberd_config:start() //創(chuàng)建config,local_config兩張表,并加載配置文件中的配置到表中
- 17. ejabberd_check:config() //檢查配置文件中指定要加載的模塊是否存在
- 18. connect_nodes() //建立到集群中其他節(jié)點的鏈接,其他節(jié)點在配置中定義
- 19. Sup = ejabberd_sup:start_link() //啟動一個supervisor,并啟動和監(jiān)控定義的子進程
詳細看下這個supervisior 的init()定義:
- {ok, {{one_for_one, 10, 1},
- [Hooks,
- NodeGroups,
- SystemMonitor,
- Router,
- SM,
- S2S,
- Local,
- Captcha,
- ReceiverSupervisor,
- C2SSupervisor,
- S2SInSupervisor,
- S2SOutSupervisor,
- ServiceSupervisor,
- HTTPSupervisor,
- HTTPPollSupervisor,
- IQSupervisor,
- STUNSupervisor,
- FrontendSocketSupervisor,
- CacheTabSupervisor,
- Listener]}}
重啟策略為one_for_one(只重啟終止的子進程自身),如果1s內重啟次數(shù)超過10則終止所有子進程和自身。列表中為子進程的定義。以Hooks為例子:
- Hooks =
- {ejabberd_hooks,
- {ejabberd_hooks, start_link, []},
- permanent,
- brutal_kill,
- worker,
- [ejabberd_hooks]}
子進程定義的格式為:{Id, StartFunc, Restart, Shutdown, Type, Modules}
id: 分配的ID
StartFunc: 啟動子進程時調用的方法
Restart: 重啟子進程時調用的方法
Shutdown: 關閉子進程時調用的方法
Type: 子進程的類型,(supervisior or worker)
Modules: 回調模塊
可以看到這里啟動了不少的子進程,從名字上大體上可以看出各個子進程的功能。
- 20. ejabberd_rdbms:start() //啟動數(shù)據(jù)庫相關模塊
- 21. ejabberd_auth:start() //啟動所有鑒權模塊
- 22. cyrsasl:start() //啟動SASL安全認證模塊
- 23. maybe_add_nameservers() //如果運行在windows系統(tǒng),則添加域名服務器(DNS)地址到erlang系統(tǒng)中
- 24. start_modules() //啟動所有節(jié)點上的定義在local_config中的模塊
- 25. ejabberd_listener:start_listeners() //啟動配置文件中的監(jiān)聽器模塊