所以我们的想法是我们需要引入一些子进程来生成/监视,但是我们需要启动监视进程,这样它们一次只能处理少于10个子进程。因此,如果我们接受35个子进程,我们需要有4个监视器,3个监视10个孩子,还有一个监视5个。
问题在于,我正在努力弄清楚为什么我为此目的编写的代码失败了。这是代码:
-module(watcher).
-import(sensor, [start/0]).
-export([start/1, stop/0]).
start(NrSlaves) ->
MasterPids = [],
MasterPid = spawn(fun() -> master_starter(NrSlaves, MasterPids) end),
register(master, MasterPid),
ok.
stop() ->
master ! die,
ok.
slave_pid_to_nr(SlavePid, SlavePids) ->
slave_pid_to_nr(SlavePid, SlavePids, 1).
slave_pid_to_nr(SlavePid, [SlavePid | _Tail], SlaveNr) ->
SlaveNr;
slave_pid_to_nr(SlavePid, [_Head | Tail], SlaveNr) ->
slave_pid_to_nr(SlavePid, Tail, SlaveNr + 1).
slave_change_pid(OldSlavePid, NewSlavePid, SlavePids) ->
lists:map(
fun(Pid) ->
if
Pid == OldSlavePid ->
NewSlavePid;
true ->
Pid
end
end,
SlavePids
).
%This is the part that errors out
master_starter(NrSlaves, MasterPids) ->
if (NrSlaves/10) =< 1 ->
MasterPids = MasterPids ++ [spawn_link(fun() -> master_start(NrSlaves) end)];
true->
MasterPids = MasterPids ++ [spawn_link(fun() -> master_start(10) end) || lists:seq(1, (NrSlaves/10))],
master_starter(NrSlaves-10, MasterPids)
end,
receive
die ->
io:fwrite("Monitor: received die~n"),
lists:foreach(fun(MasterPid) -> MasterPid ! die end, MasterPids)
end.
master_start(NrSlaves) ->
process_flag(trap_exit, true),
io:fwrite("monitor: started~n", []),
SlavePids = [spawn_link(fun() -> slave_start(SlaveNr) end) || SlaveNr <- lists:seq(1, NrSlaves)],
master_loop(SlavePids).
master_loop(SlavePids) ->
receive
die ->
io:fwrite("Monitor: received die~n"),
lists:foreach(fun(SlavePid) -> SlavePid ! die end, SlavePids);
{SlaveNr, Measurement} ->
io:fwrite("Sensor# ~p measures ~p~n", [SlaveNr, Measurement]),
master_loop(SlavePids);
{'EXIT', SlavePid, _Reason} ->
SlaveNr = slave_pid_to_nr(SlavePid, SlavePids),
io:fwrite("Monitor: Sensor ~p with PID ~p died because of a crash~n", [SlaveNr, SlavePid]),
NewSlavePid = spawn_link(fun() -> slave_start(SlaveNr) end),
NewSlavePids = slave_change_pid(SlavePid, NewSlavePid, SlavePids),
master_loop(NewSlavePids)
end.
slave_start(SlaveNr) ->
% SlavePid = lists:nth(SlaveNr, SlavePids),
io:fwrite("sensor ~p with PID ~p: started~n", [SlaveNr, self()]),
%%slave_loop(SlaveNr).
sensor:start(SlaveNr).
我收到的错误如下:&#34;流程错误&lt; 0.573.0&gt;退出值:{{badmatch,[&lt; 0.574.0&gt;]},[{watcher,master_starter,2,[{file,&#34; watcher.erl&#34;},{line,39}]}] }&#34;
任何帮助将不胜感激。它已经非常接近完成,但我只需要理解为什么它不起作用。
答案 0 :(得分:1)
我在您的代码中看到了三个问题。
变量是不可变的,MasterPids = MasterPids ++ ...
将失败并出现badmatch
错误。尝试分配新变量,例如NewPids
或MasterPids2
。
您在列表理解中缺少生成器。你应该在那里<-
,[spawn_link( ... ) || _ <- lists:seq(1, (NrSlaves/10)).
lists:seq
不接受浮动。您必须将NrSlaves/10
向上舍入为整数。您可以使用ceiling function from here(可能会稍微简化,因为您不会使用负数)。
答案 1 :(得分:0)
变量在erlang中不可变。所以
MasterPids = MasterPids ++ [spawn_link(fun() -> master_start(NrSlaves) end)];
由于您尝试修改MasterPids ,将失败