【问题标题】:How stop, terminate, shutdown and exit are related?停止、终止、关闭和退出是如何关联的?
【发布时间】:2017-06-26 16:13:45
【问题描述】:

我读了Learn Some Erlang about supervisors 并且完全迷失了。它们具有停止和终止功能

每当您想终止应用程序时,您都会关闭虚拟机的最高主管(这是通过诸如 init:stop/1 之类的函数为您完成的)。然后该主管要求其每个孩子终止。如果有些孩子是主管,他们也会这样做:

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

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

当顶级主管被要求终止时,它会在每个 Pid 上调用 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]);

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

【问题讨论】:

    标签: erlang exit shutdown terminate termination


    【解决方案1】:

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

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

    “退出信号”是进程在终止(停止或崩溃)时向与其链接的任何其他进程发出的信号。 Supervisor 与其子节点相关联,在向子节点发送关闭信号后,它将等待其退出信号 ('EXIT') 以确保它们已终止。

    当子进程(通常使用像 gen_server 这样的 OTP 行为来实现)从上面收到关闭信号时,它首先调用自己的 terminate(...) 回调函数,您可以在其中进行任何必要的清理 - 这就像 OOP 中的析构函数。

    上面gen_server 中的stop(Role) 函数只是一个帮助函数,它提供了一个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 除外)会导致接收者也死掉,除非它们捕获退出,以便可以将链接的进程组一起关闭。

    【讨论】:

    • 太棒了!我只是没有得到 init/app:stop 函数和停止消息/信号之间的关系,以及这个信号和关闭/“退出”信号之间的关系。它们有关系吗?
    • init:stop() 是一个系统级函数。它与所有正在运行的应用程序对话。 gen_server 的 stop() 函数只是一个本地便利函数,它的消息只是一个实现细节。关闭信号是 OTP 监控器/子实现的内部细节。退出信号是适用于所有 Erlang 进程的标准东西。
    • @RichardC 抱歉,您可以看看stackoverflow.com/questions/57871313/…
    猜你喜欢
    • 2013-11-10
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多