2017-02-08 23 views
3

Я прочитал Learn Some Erlang about supervisors и полностью потерян. У них есть функции остановки и завершения.Как остановить, завершить, завершить работу и выйти?

Когда вы хотите завершить работу приложения, вы должны отключить главный диспетчер VM (это делается для вас с функциями, такими как init: stop/1). Затем этот супервизор просит каждого из своих детей прекратить действие. Если некоторые из детей контролеров, они делают то же самое:

, который, кажется, чтобы отправить выключайте сообщений для recceive 'EXIT' подтверждения

Итак, остановки является для закрытия процессов. Но, позже в тексте однако, они говорят, что выхода функция (новый фрукт!) Должна быть вызваны вместо

Когда руководитель верхнего уровня просит прекратить, он вызывает выход (ChildPid, выключение) на каждом из Pids. Если ребенок является рабочим и улавливает выходы, он будет называть свою собственную функцию завершения. В противном случае он просто умрет. Когда супервизор получает сигнал выключения, он отправит его своим детям таким же образом.

Наконец, они определяют стоп функцию в модуле детского

-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: остановка определена?

Они также отправить сообщение остановки

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]); 

Тем не менее, все это выглядит беспорядок. Можете ли вы связать все вместе?

ответ

5

init:stop() означает вызов функции stop() в модуле init. Это говорит о том, что система Erlang прекрасно закрывает все запущенные приложения, а затем выходит. Это похоже на выключение операционной системы. Затем будет выполнен вызов application:stop(AppName) для каждого запущенного приложения. Они, в свою очередь, расскажут диспетчеру верхнего уровня приложения о закрытии.

«Сигнал выключения» относится к сигналу от супервизора к ребенку. Если супервизор хочет закрыть все ниже, он посылает эти сигналы своим детям.

«Выходной сигнал» - это то, что процесс отправляет, когда он завершается (останавливается или падает) на любые другие связанные с ним процессы.Супервизор связан с его дочерними элементами, и после того, как он отправил сигналы выключения детям, он будет ожидать их выходных сигналов ('EXIT'), чтобы быть уверенным, что они прекратились.

Когда ребенок процесс (обычно реализуется с использованием поведения OTP как gen_server получает сигнал завершения сверху, первым называет свою собственную функцию terminate(...) обратного вызова, где вы можете сделать любую необходимую очистку - это как метод деструкторов в объектно-ориентированном программировании

.

Функция 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) заставляют приемников также умереть, если они не улавливают выходы, так что группы связанных процессов могут быть сведены вместе.

+0

Отлично! Я просто не получил отношения между функцией init/app: stop и остановил сообщение/сигнал и между этим сигналом и выключения/«Выход». Связаны ли они? – Val

+0

init: stop() - функция системного уровня. Он говорит обо всех запущенных приложениях. Функция stop() gen_server - это только локальная функция удобства, и ее сообщение является просто детальностью реализации. Сигналы выключения являются внутренней деталью реализации супервизора OTP/дочернего элемента. Сигналы выхода являются стандартными для всех процессов Erlang. – RichardC