这个启动脚本默认是在$ROOT/bin/start.boot文件,所以我们查看一下相应的start.script文件,内容如下

%% script generated at {2012,11,27} {19,37,10}
{script,
    {"OTP  APN 181 01","R15B03"},
    [{preLoaded,
         [erl_prim_loader,erlang,init,otp_ring0,prim_file,prim_inet,prim_zip,
          zlib]},
     {progress,preloaded},
     {path,["$ROOT/lib/kernel-2.15.3/ebin","$ROOT/lib/stdlib-1.18.3/ebin"]},
     {primLoad,[error_handler]},
     {kernel_load_completed},
     {progress,kernel_load_completed},
     {path,["$ROOT/lib/kernel-2.15.3/ebin"]},
     {primLoad,
         [application,application_controller,application_master,
          application_starter,auth,code,code_server,disk_log,disk_log_1,
          disk_log_server,disk_log_sup,dist_ac,dist_util,erl_boot_server,
          erl_ddll,erl_distribution,erl_epmd,erl_reply,error_logger,
          erts_debug,file,file_io_server,file_server,gen_sctp,gen_tcp,gen_udp,
          global,global_group,global_search,group,heart,hipe_unified_loader,
          inet,inet6_sctp,inet6_tcp,inet6_tcp_dist,inet6_udp,inet_config,
          inet_db,inet_dns,inet_gethost_native,inet_hosts,inet_parse,inet_res,
          inet_sctp,inet_tcp,inet_tcp_dist,inet_udp,kernel,kernel_config,net,
          net_adm,net_kernel,os,packages,pg2,ram_file,rpc,seq_trace,
          standard_error,user,user_drv,user_sup,wrap_log_reader]},
     {path,["$ROOT/lib/stdlib-1.18.3/ebin"]},
     {primLoad,
         [array,base64,beam_lib,binary,c,calendar,dets,dets_server,dets_sup,
          dets_utils,dets_v8,dets_v9,dict,digraph,digraph_utils,edlin,
          edlin_expand,epp,erl_bits,erl_compile,erl_eval,erl_expand_records,
          erl_internal,erl_lint,erl_parse,erl_posix_msg,erl_pp,erl_scan,
          erl_tar,error_logger_file_h,error_logger_tty_h,escript,ets,
          eval_bits,file_sorter,filelib,filename,gb_sets,gb_trees,gen,
          gen_event,gen_fsm,gen_server,io,io_lib,io_lib_format,io_lib_fread,
          io_lib_pretty,lib,lists,log_mf_h,math,ms_transform,orddict,ordsets,
          otp_internal,pg,pool,proc_lib,proplists,qlc,qlc_pt,queue,random,re,
          sets,shell,shell_default,slave,sofs,string,supervisor,
          supervisor_bridge,sys,timer,unicode,win32reg,zip]},
     {progress,modules_loaded},
     {path,["$ROOT/lib/kernel-2.15.3/ebin","$ROOT/lib/stdlib-1.18.3/ebin"]},
     {kernelProcess,heart,{heart,start,[]}},
     {kernelProcess,error_logger,{error_logger,start_link,[]}},
     {kernelProcess,application_controller,
         {application_controller,start,
             [{application,kernel,
                  [{description,"ERTS  CXC 138 10"},
                   {vsn,"2.15.3"},
                   {id,[]},
                   {modules,
                       [application,application_controller,application_master,
                        application_starter,auth,code,packages,code_server,
                        dist_util,erl_boot_server,erl_distribution,erl_reply,
                        error_handler,error_logger,file,file_server,
                        file_io_server,global,global_group,global_search,
                        group,heart,hipe_unified_loader,inet6_tcp,
                        inet6_tcp_dist,inet6_udp,inet6_sctp,inet_config,
                        inet_hosts,inet_gethost_native,inet_tcp_dist,kernel,
                        kernel_config,net,net_adm,net_kernel,os,ram_file,rpc,
                        user,user_drv,user_sup,disk_log,disk_log_1,
                        disk_log_server,disk_log_sup,dist_ac,erl_ddll,
                        erl_epmd,erts_debug,gen_tcp,gen_udp,gen_sctp,inet,
                        inet_db,inet_dns,inet_parse,inet_res,inet_tcp,
                        inet_udp,inet_sctp,pg2,seq_trace,standard_error,
                        wrap_log_reader]},
                   {registered,
                       [application_controller,erl_reply,auth,boot_server,
                        code_server,disk_log_server,disk_log_sup,
                        erl_prim_loader,error_logger,file_server_2,
                        fixtable_server,global_group,global_name_server,heart,
                        init,kernel_config,kernel_sup,net_kernel,net_sup,rex,
                        user,os_server,ddll_server,erl_epmd,inet_db,pg2]},
                   {applications,[]},
                   {included_applications,[]},
                   {env,[{error_logger,tty}]},
                   {maxT,infinity},
                   {maxP,infinity},
                   {mod,{kernel,[]}}]}]}},
     {progress,init_kernel_started},
     {apply,
         {application,load,
             [{application,stdlib,
                  [{description,"ERTS  CXC 138 10"},
                   {vsn,"1.18.3"},
                   {id,[]},
                   {modules,
                       [array,base64,beam_lib,binary,c,calendar,dets,
                        dets_server,dets_sup,dets_utils,dets_v8,dets_v9,dict,
                        digraph,digraph_utils,edlin,edlin_expand,epp,
                        eval_bits,erl_bits,erl_compile,erl_eval,
                        erl_expand_records,erl_internal,erl_lint,erl_parse,
                        erl_posix_msg,erl_pp,erl_scan,erl_tar,
                        error_logger_file_h,error_logger_tty_h,escript,ets,
                        file_sorter,filelib,filename,gb_trees,gb_sets,gen,
                        gen_event,gen_fsm,gen_server,io,io_lib,io_lib_format,
                        io_lib_fread,io_lib_pretty,lib,lists,log_mf_h,math,
                        ms_transform,orddict,ordsets,otp_internal,pg,pool,
                        proc_lib,proplists,qlc,qlc_pt,queue,random,re,sets,
                        shell,shell_default,slave,sofs,string,supervisor,
                        supervisor_bridge,sys,timer,unicode,win32reg,zip]},
                   {registered,
                       [timer_server,rsh_starter,take_over_monitor,
                        pool_master,dets]},
                   {applications,[kernel]},
                   {included_applications,[]},
                   {env,[]},
                   {maxT,infinity},
                   {maxP,infinity}]}]}},
     {progress,applications_loaded},
     {apply,{application,start_boot,[kernel,permanent]}},
     {apply,{application,start_boot,[stdlib,permanent]}},
     {apply,{c,erlangrc,[]}},
     {progress,started}]}.

 

以下是init模块中关于启动脚本解析执行的一段源码:

%解析到process标签时,输出调试信息,通知init主进程
eval_script([{progress,Info}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) -> debug(Deb,{progress,Info}), init ! {self(),progress,Info}, eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);

%解析到preLoaded标签,直接略过 eval_script([{preLoaded,_}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) -> eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);

%解析到path标签时,根据启动参数中'-path'的设置来确定是否整合路径,false则将Path与启动参数中'-pa' '-pz'的路径进行整合,设置erl_prim_loader的加载路径 eval_script([{path,Path}|CfgL],Init,{Pa,Pz},Vars,false,Ph,Deb,PathChoice) -> RealPath0 = make_path(Pa, Pz, Path, Vars), RealPath = patch_path(RealPath0, PathChoice), erl_prim_loader:set_path(RealPath), eval_script(CfgL,Init,{Pa,Pz},Vars,false,Ph,Deb,PathChoice); eval_script([{path,_}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) -> %% Ignore, use the command line -path flag. eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);

%解析到kernel_load_completed标签时候, 根据启动mode的不同,区分interactive | embedded,
分别标示,在后面的primLoad时候,embedded时候,标示为true,则必须加载模块,否则在interactive模式下,由code_server动态加载模块 eval_script([{kernel_load_completed}|CfgL],Init,PathFs,Vars,P,{_,embedded,Par},Deb,PathChoice) -> eval_script(CfgL,Init,PathFs,Vars,P,{true,embedded,Par},Deb,PathChoice); eval_script([{kernel_load_completed}|CfgL],Init,PathFs,Vars,P,{_,E,Par},Deb,PathChoice) -> eval_script(CfgL,Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice);
%解析到primLoad标签时候,首先根据mode不同,确定是否加载,确定是一般加载方式还是并行加载方式。 eval_script([{primLoad,Mods}|CfgL],Init,PathFs,Vars,P,{true,E,Par},Deb,PathChoice) when is_list(Mods) -> if Par =:= true -> par_load_modules(Mods,Init); true -> load_modules(Mods) end, eval_script(CfgL,Init,PathFs,Vars,P,{true,E,Par},Deb,PathChoice);
eval_script([{primLoad,_Mods}|CfgL],Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice) -> %% Do not load now, code_server does that dynamically! eval_script(CfgL,Init,PathFs,Vars,P,{false,E,Par},Deb,PathChoice);

%解析到kernelProcess标签时,启动一些特别的进程,这些进程直接被init进程link和监控,
在这个启动脚本中,主要就是heart进程,error_logger进程,还有application_controller进程 eval_script([{kernelProcess,Server,{Mod,Fun,Args}}|CfgL],Init, PathFs,Vars,P,Ph,Deb,PathChoice) -> debug(Deb,{start,Server}), start_in_kernel(Server,Mod,Fun,Args,Init), eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice);

%解析到apply标签,则直接调用函数。 eval_script([{apply,{Mod,Fun,Args}}|CfgL],Init,PathFs,Vars,P,Ph,Deb,PathChoice) -> debug(Deb,{apply,{Mod,Fun,Args}}), apply(Mod,Fun,Args), eval_script(CfgL,Init,PathFs,Vars,P,Ph,Deb,PathChoice); eval_script([],_,_,_,_,_,_,_) -> ok; eval_script(What,_,_,_,_,_,_,_) -> exit({'unexpected command in bootfile',What}).

 

以上的启动脚本,我们可以看到在启动过程中执行了启动kernel应用的操作,和stdlib的操作,

而当我启动完虚拟机后,发觉启动的application只有一个,就是kernel,这是因为:

The mod key can be omitted for applications without processes, typically code libraries such as the application STDLIB.

在app文件中如果没有定义key的话是不会有进程作为application启动的,

所以真正在引导程序中启动的application只有kernel. stdlib只是单纯将所有涉及modules载入而已

这里应用启动是直接使用的application:start_boot,而其底层调用的实际是application_controller:start_boot_application方法,

其实application:start_boot和application:start方法本质上没太大区别,

但底层使用的application_controller:start_boot_application方法是不被暴露的,仅仅在启动引导时候使用的。

 

启动脚本的最后还调用了c:erlangrc/0函数这个是用来执行目录下.erlang文件代码的。基本就是虚拟机启动时的一个钩子。你可以放些路径设置神马的在里面。

That's all.

 

 

 posted on 2012-12-27 17:27  文武双全大星星  阅读(669)  评论(0编辑  收藏  举报