use*_*860 0 erlang spawn gen-server
我有两个gen_server模块.
第一个serv.erl
-module(serv).
-behaviour(gen_server).
-export([init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
code_change/3,
terminate/2,
start_link/0
]).
start_link() ->
gen_server:start_link(?MODULE, [], []).
init([]) ->
process_flag(trap_exit, true),
spawn_link(user, start_link,[]),
{ok, []}.
handle_call(_E, _From, State) ->
{noreply, State}.
handle_cast(_Message, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
handle_info(Message, State) ->
{noreply, State}.
code_change(_OldVersion, State, _Extra) ->
{ok, State}.
Run Code Online (Sandbox Code Playgroud)
和user.erl(除了init/1完全相同):
init([]) ->
{ok, []}.
Run Code Online (Sandbox Code Playgroud)
我以为服务器会永远存在.如果第一台服务器死了,另一台服务器会收到{'EXIT',Pid,Reason}消息.
但是如果你通过serv:start_link()启动模块,用户模块将在启动后立即退出,并显示消息{'EXIT',Pid,normal}.为什么用户会死?
spawn并且spawn_link是用于启动新进程的两个基本Erlang函数.双方将创建一个进程,然后调用与作为参数指定参数的函数spawn/ spawn_link.当该功能结束时,进程会自动终止并退出原因normal.这些功能之间的区别在于,spawn_link它还在两个进程之间创建了一个链接.
该gen_server:start_link函数不仅仅是通过启动行为创建流程,然后运行提供所有行为功能的行为顶循环.除此之外,调用回调函数init来初始化行为,然后返回{ok,State}告诉行为已经初始化并且进展顺利,这是传递给所有回调的本地状态.gen_server的回调函数不是直接调用,而是由行为调用.
因此,当您显式生成一个刚刚运行该init函数的进程时,它将在init函数结束后立即终止.这就是这里发生的事情.
该{'EXIT',Pid,Reason}消息来自被连接的过程,这一过程被捕获退出.当进程死亡时,退出信号从死亡进程发送到它所链接的所有进程.当此信号到达进程陷阱退出时,它将转换为正常消息并放入该进程消息队列中.这就是你在这里看到的.请注意,由于链接和陷印退出,所有这些都是自动完成的.
我希望有所帮助.对不起,这里有点过分教诲.