- application:start(ejabberd).
application用来表示一个可以单独启动和停止、并被复用的程序单元。通常一个application都有一个同名的app文件来定义。
对于系统工具(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 定义了应用程序的回调模块和启动参数。 在应用程序启动时会由主导进程来调用这个模块的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;
我们可以看到它调用了一系列的方法和函数来完成整个应用的启动。
- 1. ejabberd_loglevel:set(4) //设置日志级别
- 2. write_pid_file() //将当前进程标识写到环境变量EJABBERD_PID_PATH定义的文件中
- 3. application:start(sasl) //启动sasl应用 ,具体sasl应用所提供的服务请查看<a href="http://www.erlang.org/doc/man/sasl_app.html">sasl</a>
- 4. randoms:start() //注册一个名为random_generator,用当前时间做种子生成随机字符串的进程
- 5. db_init() //初始化并启动本地的mnesia数据库,并等待直到所有表可用或超时
- 7. stringprep_sup:start_link() //启动一个监控进程
- 8. xml:start() //提供xml处理功能
- 9. start() //注册进程自身为ejabberd,设置日志目录,加载驱动
- 10. translate:start()//从环境变量EJABBERD_MSGS_PATH定义的位置找*.msg 并加载到ets:translations 表中(国际化)
- 12. ejabberd_ctl:init() //创建两张表ejabberd_ctl_cmds,ejabberd_ctl_host_cmd
- 13. ejabberd_commands:init() //创建表ejabberd_commands
- 14. ejabberd_admin:start() //注册常用的ejabberd_command到表ejabberd_commands
这里的ejabberd_command类似于java中的虚方法,这个ejabberd_command 具有指定的名称、指定类型数量参数、指定类型返回值。
例如:
#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}] 参数,返回{res, restuple}的虚方法。
- 15. gen_mod:start() //创建表ejabberd_modules
- 16. ejabberd_config:start() //创建config,local_config两张表,并加载配置文件中的配置到表中
- 17. ejabberd_check:config() //检查配置文件中指定要加载的模块是否存在
- 18. connect_nodes() //建立到集群中其他节点的链接,其他节点在配置中定义
- 19. Sup = ejabberd_sup:start_link() //启动一个supervisor,并启动和监控定义的子进程
详细看下这个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内重启次数超过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() //启动数据库相关模块
- 21. ejabberd_auth:start() //启动所有鉴权模块
- 22. cyrsasl:start() //启动SASL安全认证模块
- 23. maybe_add_nameservers() //如果运行在windows系统,则添加域名服务器(DNS)地址到erlang系统中
- 24. start_modules() //启动所有节点上的定义在local_config中的模块
- 25. ejabberd_listener:start_listeners() //启动配置文件中的监听器模块
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。