进程单向监控-Monitor
link方式可以建立进程之间的双向链接关系,我们可以通过monitor实现单向的监控,这在gen_server代码里面可以看到对应的例子
gen_server代码片段:
do_multi_call(Nodes, Name, Req, Timeout) ->
Tag = make_ref(),
Caller = self(),
Receiver =
spawn(
fun() ->
%% Middleman process. Should be unsensitive to regular
%% exit signals. The sychronization is needed in case
%% the receiver would exit before the caller started
%% the monitor.
process_flag(trap_exit, true),
Mref = erlang:monitor(process, Caller), %建立单向监控
receive
{Caller,Tag} ->
Monitors = send_nodes(Nodes, Name, Tag, Req),
TimerId = erlang:start_timer(Timeout, self(), ok),
Result = rec_nodes(Tag, Monitors, Name, TimerId),
exit({self(),Tag,Result});
{'DOWN',Mref,_,_,_} -> %接受监控消息
%% Caller died before sending us the go-ahead.
%% Give up silently.
exit(normal)
end
end),
Mref = erlang:monitor(process, Receiver),
Receiver ! {self(),Tag},
receive
{'DOWN',Mref,_,_,{Receiver,Tag,Result}} ->
Result;
{'DOWN',Mref,_,_,Reason} ->
%% The middleman code failed. Or someone did
%% exit(_, kill) on the middleman process => Reason==killed
exit(Reason)
end.
handle_call({subscribe, PId}, _From, #state{subscribers = Subscribers} = State) ->
NSubscribers = ordsets:add_element(PId, Subscribers),
erlang:monitor(process, PId),
{reply, {ok, ok}, State#state{subscribers = NSubscribers}};
handle_info({'DOWN', _MRef, _, PId, _Reason}, #state{subscribers = Subscribers} = State) ->
NSubscribers = ordsets:del_element(PId, Subscribers),
{noreply, State#state{subscribers = NSubscribers}};