OTP中supervisor启动过程
来源:互联网 发布:基础代谢 知乎 编辑:程序博客网 时间:2024/06/15 08:39
转载自庆亮的博客-webgame架构
从rabbit_sup模块开始看起:
rabbit_sup模块的start_link是被rabbit app模块的start/2方法所调用的
rabbit.erl文件:
start(normal, []) ->
{ok, SupPid} = rabbit_sup:start_link(),
rabbit_sup.erl文件:
-define(SERVER, ?MODULE).
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
这里的?SERVER和?MODULE是一样的值,都为rabbit_sup 。
跳转到supervisor.erl文件:
start_link(SupName, Mod, Args) ->
gen_server:start_link(SupName, supervisor, {SupName, Mod, Args}, []).
看到supervisor的start_link实际上调用的是gen_server的start_link方法,调用的时候将supervisor作为一个参数传递过去了。
这样到目前为止我们的调用实际为:
gen_server:start_link({local, rabbit_sup}, supervisor, {{local, rabbit_sup}, rabbit_sup, []}, []).
gen_server.erl文件:
start_link(Mod, Args, Options) ->
gen:start(?MODULE, link, Mod, Args, Options).
start_link(Name, Mod, Args, Options) ->
gen:start(?MODULE, link, Name, Mod, Args, Options).
gen_server的start_link方法调用了gen模块的start方法,实际调用为:
gen:start(gen_server, link, {local, rabbit_sup},supervisor, {{local, rabbit_sup}, rabbit_sup, []}, []).
gen.erl文件:
start(GenMod, LinkP, Name, Mod, Args, Options) ->
case where(Name) of
undefined ->
do_spawn(GenMod, LinkP, Name, Mod, Args, Options);
Pid ->
{error, {already_started, Pid}}
end.
start之前判断是否已经创建了该process,没有则创建,有则返回错误!
do_spawn(GenMod, link, Name, Mod, Args, Options) ->
Time = timeout(Options),
proc_lib:start_link(?MODULE, init_it,
[GenMod, self(), self(), Name, Mod, Args, Options],
Time,
spawn_opts(Options));
do_spawn(GenMod, _, Name, Mod, Args, Options) ->
Time = timeout(Options),
proc_lib:start(?MODULE, init_it,
[GenMod, self(), self, Name, Mod, Args, Options],
Time,
spawn_opts(Options)).
实际又是调用了gen模块的init_it方法,采用的link的spawn方式。
init_it(GenMod, Starter, Parent, Mod, Args, Options) ->
init_it2(GenMod, Starter, Parent, self(), Mod, Args, Options).
init_it(GenMod, Starter, Parent, Name, Mod, Args, Options) ->
case name_register(Name) of
true ->
init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options);
{false, Pid} ->
proc_lib:init_ack(Starter, {error, {already_started, Pid}})
end.
首先尝试注册这个名字,如果发现已经注册,则通知父进程已经创建了。否则跳转到init_in2,
init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options) ->
GenMod:init_it(Starter, Parent, Name, Mod, Args, Options).
这时又跳转到gen_server:init_it方法。
init_it(Starter, self, Name, Mod, Args, Options) ->
init_it(Starter, self(), Name, Mod, Args, Options);
init_it(Starter, Parent, Name0, Mod, Args, Options) ->
Name = name(Name0),
Debug = debug_options(Name, Options),
case catch Mod:init(Args) of
{ok, State} ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, State, Mod, infinity, Debug);
{ok, State, Timeout} ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, State, Mod, Timeout, Debug);
{stop, Reason} ->
%% For consistency, we must make sure that the
%% registered name (if any) is unregistered before
%% the parent process is notified about the failure.
%% (Otherwise, the parent process could get
%% an 'already_started' error if it immediately
%% tried starting the process again.)
unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
ignore ->
unregister_name(Name0),
proc_lib:init_ack(Starter, ignore),
exit(normal);
{'EXIT', Reason} ->
unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
Else ->
Error = {bad_return_value, Else},
proc_lib:init_ack(Starter, {error, Error}),
exit(Error)
end.
又是调用了supervisor的init方法
init({SupName, Mod, Args}) ->
process_flag(trap_exit, true),
case Mod:init(Args) of
{ok, {SupFlags, StartSpec}} ->
case init_state(SupName, SupFlags, Mod, Args) of
{ok, State} when ?is_simple(State) ->
init_dynamic(State, StartSpec);
{ok, State} ->
init_children(State, StartSpec);
Error ->
{stop, {supervisor_data, Error}}
end;
ignore ->
ignore;
Error ->
{stop, {bad_return, {Mod, init, Error}}}
end.
呵呵,到了这里终于调用了rabbit_sup的init方法了,根据不同的init返回值做不同的启动子进程的操作。
- OTP中supervisor启动过程
- OTP中supervisor启动过程
- 理解Erlang/OTP Supervisor
- erlang OTP supervisor 图解分析
- erlang OTP supervisor 图解分析
- Erlang/OTP 监督者(Supervisor)
- OTP Design Principles: Supervisor Behaviour(经典)
- [Erlang 0030] 理解Erlang/OTP Supervisor
- Erlang学习:OTP - Application & supervisor & gen_server
- OTP supervisor的monitor_child是否有漏洞
- storm中supervisor的启动exit问题
- storm中supervisor的启动exit问题
- nodejs 4.0中supervisor、express启动项目
- OTP行为模式浅析之(gen_server、application、supervisor)
- Erlang学习:A non-OTP supervisor for a non-OTP server
- 安装启动 Supervisor
- supervisor后台启动shadowsocks
- storm启动supervisor源码分析-supervisor.clj
- ubuntu下输入adb devices出现???????????? no permissions 解决方法解决方案
- 如何发送hmtl格式的邮件内容(网页邮件)
- sql datetime 格式转换
- Oracle 内存管理
- JQUERY validate验证
- OTP中supervisor启动过程
- 邮件相关端口
- 树形菜单大集合,带checkbox,带右键菜单,重命名,动态修改等
- Java 基础一些代码练习笔记(Propertise环境变量)
- 0 欧姆电阻
- windows常用命令
- 将程序关联成Android系统默认打开程序
- jquery.cookie.js操作cookie实现记住密码
- ExtJS 3 不能在IE9下正常运行的简单解决办法