我看了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]);
然而,这看起来一团糟。你能把这些东西捆绑在一起吗?
答案 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
除外)导致接收器也死掉,除非它们捕获出口,以便可以将一组链接的进程放在一起。