关于设置捕获信号的gen_server在-eval无法正常启动问题分析

一、erl -eval “p_server:start()”原理分析。
 
         erlang的启动过程从erlexec开始,该文件存在于otp_src_R15B01/erts/etc/common/erlexec.c 文件中。erlexec的main函数首先分析erl传入的参数和环境变量,选择正确版本的beam可执行文件,然后将传入的参数整理好,加入一些默认参数,最后通过系统调用execv运行beam虚拟机。在虚拟机启动的过程先要经过底层初始化,处理各种参数,设置信号处理函数,虚拟机本身初始化,共享内存初始化,加载相关模块,然后启动第一个进程init,执行init的boot方法,init进程本身设置了process_flag(trap_exit,true),通过分析boot方法了解此过程:
 
1 boot(BootArgs) ->
2     register(init, self()),
3     process_flag(trap_exit, true),
4     start_on_load_handler_process(),
5     {Start0,Flags,Args} = parse_boot_args(BootArgs),
6     Start = map(fun prepare_run_args/1, Start0),
7     Flags0 = flags_to_atoms_again(Flags),
8     boot(Start,Flags0,Args).
第2行将当前进程注册为init,于是我们就有了init进程。第4行启动了一个新的进程ON_LOAD_HANDLER,这个进程处理一些和加载相关的事件,侦听某些消息的到来,处理完后自动退出,然后对传入的参数做一些处理,Start是erl -s参数传入的要运行的MFA列表,Flags0是调用erl传入的一些标志,Args是erl -extra 传入的一些额外参数。接下来这些参数传入boot/3。在boot/3中会调用do_boot/2,do_boot/2中会再新启一个进程执行do_boot/3,do_boot/3在执行完一系列动作之后调用start_em/1执行eval之后的代码,该进程退出后boot_loop/2收到'EXIT'消息,init进程进入loop/1循环,此时,init作为初始化的任务已经完成。
 
二、设置捕获信号的gen_server在-eval无法正常启动原因。
 
        根据一中的分析,我们能很明确知道,init进程会生成两个进程:一个是ON_LOAD_HANDLER;一个是do_boot进程。-eval后的代码并不是init进程本身去执行的,而是由do_boot进程来执行的,并且此进程做完一系列动作后会退出。当gen_server设置了捕获信号后,启动它的do_boot进程退出时,会发退出信号后gen_server,因此该gen_server会自动退出。原本do_boot进程在启动gen_server时,两个进程间会links,但是当do_boot进程退出时,该gen_server进程的linksset中为空。

你可能感兴趣的:(关于设置捕获信号的gen_server在-eval无法正常启动问题分析)