停止,终止,关闭和退出的关系如何?

时间:2017-02-08 20:53:26

标签: erlang exit shutdown terminate termination

我看了Learn Some Erlang about supervisors并完全迷失了。他们有停止和终止功能

  

每当您想要终止某个应用程序时,您都会关闭VM的顶级管理员(这是通过init:stop / 1等功能为您完成的)。然后该主管要求其每个孩子终止。如果有些孩子是主管,他们会这样做:

似乎发送关闭消息以接收'退出'确认

因此,调用 stop 来关闭进程。但是,在文本的后面,他们说必须调用退出函数(一个新的水果!)

  

当要求顶级主管终止时,它会在每个Pids上调用exit(ChildPid,shutdown)。如果孩子是一个工人并且陷阱退出,它将调用它自己的终止函数。否则,它就会死去。当主管获得关机信号时,它会以同样的方式将其转发给自己的孩子。

最后,他们在子模块中定义了 stop 函数

-module(musicians).
-behaviour(gen_server).

-export([start_link/2, stop/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, code_change/3, terminate/2]).

stop(Role) -> gen_server:call(Role, stop).

init:stop 定义在哪里?

他们还会发送停止消息

handle_call(stop, _From, S=#state{}) -> {stop, normal, ok, S};

他们的 handle_info

handle_info(timeout, S = #state{name=N, skill=bad}) ->
case random:uniform(5) of
  1 -> io:format("~s played a false note. Uh oh~n",[N]),
    {stop, bad_note, S};
  _ -> io:format("~s produced sound!~n",[N]),
    {noreply, S, ?DELAY}
end;

阐明其答复与终止

之间的联系
terminate(normal, S) ->
  io:format("~s left the room (~s)~n",[S#state.name, S#state.role]);
terminate(bad_note, S) ->
  io:format("~s sucks! kicked that member out of the band! (~s)~n",
    [S#state.name, S#state.role]);
terminate(shutdown, S) ->
  io:format("The manager is mad and fired the whole band! "
    "~s just got back to playing in the subway~n", [S#state.name]);

然而,这看起来一团糟。你能把这些东西捆绑在一起吗?

1 个答案:

答案 0 :(得分:4)

init:stop()表示调用模块stop()中的函数init。这告诉Erlang系统很好地关闭所有正在运行的应用程序,然后退出。这就像关闭操作系统一样。然后将为每个正在运行的应用程序执行调用application:stop(AppName)。这些将反过来告诉应用程序的顶级主管关闭。

“关机信号”是指从主管到儿童的信号。如果主管想要关闭它下面的所有东西,它会将这些信号发送给它的孩子。

“退出信号”是一个进程在终止(停止或崩溃)到链接到它的任何其他进程时发出的信号。主管与其子女相关联,在向孩子发送关机信号后,它会等待退出信号('EXIT')以确保他们已经终止。

当子进程(通常使用像gen_server这样的OTP行为从上面获取关闭信号时,它首先调用它自己的terminate(...)回调函数,在那里你可以进行任何必要的清理 - 它就像一个析构函数方法OOP。

上面stop(Role)中的gen_server函数只是一个辅助函数,提供了一个API,用于要求此服务器很好地停止(不涉及主管)。您可以直接使用gen_server:call(Role, stop),但您必须知道内部实现也使用原子stop作为停止消息。隐藏API后面的这些细节是很好的做法。

最后,内置函数(BIF)exit(Pid, shutdown)命名不佳,因为它的作用是它向另一个进程发送信号而不影响执行调用的进程。可以将其视为send_exit_signal(Pid, shutdown)。它不应该与终止执行它的进程的BIF exit(Info)混淆(通过引发异常)。这两个BIF都属于erlang模块。

此外,在这样的非正式文本中,信号可能被称为“消息”,但它不是 - 它不会在接收者的邮箱中结束,除非接收者是“诱捕”退出“(设置了trap_exit进程标志)。普通消息实际上是一种特殊的信号,总是发送到邮箱;退出信号(normal除外)导致接收器也死掉,除非它们捕获出口,以便可以将一组链接的进程放在一起。