Erlang Application的启动方式
-
整体流程图如下所示
-
启动start
-
调用过程application:start;application:ensure_all_started
-
application:load
-
application_controller:start_application
-
gen_server:call(application_controller, {start_application, AppName, RestartType}, infinity)
发消息给application_controller,通过application_controller来控制application
-
-
application_controller接着启动app
-
spawn_starter(From, AppName, S, normal)
spawn_link(application_controller, init_starter, [From, AppName, S, normal])
异步启动相应的application -
application_controller:start_appl(Appl, S, Type)
-
application_master:start_link(ApplData, Type)启动相应的application_master
-
proc_lib:start_link(application_master, init, [application_controller, self(), ApplData, Type])
因为需要在application没有完全启动完成之前,给调用者返回
-
-
application_master:init启动master进程
-
link(Parent)与父进程启动关联
-
修改application的group_leader
-
插入ac_tab这个application的主进程,进程进入init_loop等待loop进程启动完成
-
-
start_it(State,Type)启动
-
process_flag(trap_exit, true)
-
启动相应的进程
-
start_it_old/4旧版本启动进程
-
Mod(.app中设置的application的启动mod):start(Type, A),启动成功返回相应的Pid
-
link(Pid)
-
给application_master启动的主进程发送启动成功的消息 From ! {Tag, {ok, self()}}
-
进程进入loop_it的进程
-
-
start_it_new/4新版本启动进程
-
application_master:start_the_app/5
-
application_master:start_supervisor/3
Mod:start/2启动 -
link(Pid)
-
application_starter:start/3循环启动相应的apps
-
-
给application_master启动的主进程发送启动成功的消息 From ! {Tag, {ok, self()}}
-
进程进入loop_it的进程
-
-
-
进程进入init_loop/4的循环,直到收到{Tag, Res}的返回,start_it/2返回新产生的Pid
-
-
set_timer设置超时时间
-
unlink(Starter)取消和Starter的关联,启动进程为临时进程
-
proc_lib:init_ack(Starter, {ok, self()}) 返回启动进程
-
进程进入main_loop(Parent, State)循环
-
-
gen_server:cast(application_controller, {application_started, AppName, {ok, PID}})
-
-
停止stop
-
application:stop 调用过程
-
application_controller:stop_application/1
-
gen_server:call(application_controller, {stop_application, AppName}, infinity)
-
-
application_controller:stop_appl/3
-
unlink/1 取消和app的根进程的关联关系
-
application_master:stop(ID)
-
此处为同步stop的操作 send, receive的方式
-
AppMaster ! {Req, Tag(make_ref()产生的), self()}
-
-
-
此处的操作交给master进程main_loop,handle_msg({stop,..})
-
catch terminate(normal, State)终止进程
-
_ = [From ! {Tag, error} || {_, Tag, From} <- Reqs],所有的请求全部返回error
-
terminate_child停掉所有的child(这里的child指的是loop进程)
- Child ! {self(), terminate} %% 停止掉此处控制群移交到loop进程
-
-
loop进程在loop_it接收到terminate的消息
-
Mod:prep_stop(Mod, AppState)
-
exit(Child, shutdown)这里的child指的是application启动的app的根进程
-
receive ‘EXIT’ application全部停止之后,loop进程会收到终止的EXIT singnal
-
Mod:stop(NewAppState)停止application之后的清理工作
-
exit(normal)停止相应的loop进程,接下来的清理工作交换
-
-
terminate_loop阻塞等待loop的终止
- From ! {Tag, ok}
-
receive {‘Tag’, ok} 通过erlang:monitor(process, AppMaster)
-
info_exited(AppName, stopped, Type) error_logger打印出App停止的日志
-
ets:delete(ac_tab, {application_master, AppName}) 从ac_tab中移除相应的App
-
-
application_controller:cntrl/3 通知control进程application已经停止
-
-
-
init:stop调用过程
-
init ! {stop, stop}
-
init:stop(stop, State)
-
clear_system/2
-
shutdown_pids
-
shutdown_timer
-
catch shutdown(Kernel, BootPid, Timer, State)
shutdown_kernel_pid/4
-
Pid ! {‘EXIT’, BootPid, shutdown}
-
shutdown_loop等待application_controller正常终止
接下来控制权交给AC进程
- application_controller:terminate/2
循环停止所有的app,逻辑和applicaiton:stop的逻辑可以统一
- application_controller:terminate/2
-
-
kill_app_pids
-
kill_all_ports
-
flush_timout
-
-
unload(Heart)
-
-
do_stop(stop, State)
-
-