一、进程与消息
下面的实验用到的测试代码
-module(dist).
-compile([export_all]).
start() ->
spawn(?MODULE, echo, []).
echo() ->
receive
{M, Pid} -> Pid ! {M, self()} % Pid可以代表本地进程,也可以是远程节点上的进程
end,
echo().
0. 进程及其pid
启动一个进程
Pid = spawn(dist, echo, [])
通过进程pid,可以直接给这个进程发消息
Pid ! {"hi, myself", self()}.
1. 本地注册
如果在本地节点node1中注册一个进程
register(test1,Pid).
可以通过BIF函数registered()察看本节点的所有注册进程。
在本节点内通过注册名给该进程发送消息:
test1 ! Msg.
在远程节点node2上给该进程发生消息
{test1, nodeName@node1} ! {"hi from node1", self()}.
2. 全局注册
另外一种方法是对该进程在所有节点组成的集群中进行全局注册
对进程进行全局注册
$ erl -name node1@10.0.0.11 -setcookie abc
(node1@10.0.0.11)1> nodes().
['node2@10.0.0.22']
(node1@10.0.0.11)2> Pid = dist:start().
<0.45.0>
(node1@10.0.0.11)3> global:register_name(echo_srv, Pid).
(node1@10.0.0.11)4>
(node1@10.0.0.11)5>
通过全局注册名发送消息。很遗憾不能通过 ! 给全局注册的远程进程发消息,只能通过global:send/2函数。
$ erl -name node2@10.0.0.22 -setcookie abc
(node2@10.0.0.22)1> net_kernel:connect('node1@10.0.0.11').
(node2@10.0.0.22)2> global:send(echo_srv, {"hello", self()}).
<5888.45.0>
(node2@10.0.0.22)3> flush().
Shell got {"hello",<5888.45.0>}
3. 通过进程pid发送消息
一般对通过进程pid发送消息都很熟悉。实际上,节点之间也可以通过进程号pid发消息,前提是你要知道远程节点的pid。
前面的例子中可以看到远程进程的pid是<5888.45.0>,当然也可以通过global:whereis_name/1函数查询全局注册进程的pid:
(node2@10.0.0.22)4> RemotePid = global:whereis_name(echo_srv).
<5888.45.0>
注意到,node1上本地进程pid的格式是<0.45.0>,第一个数字是0,而在远程节点node2上看到的pid就成了<5888,45,0>。当在节点间发送pid数据时,erlang会自动处理这种转化。
通过BIF函数pid/3,也可以由这3个数字计算出一个进程pid,本地的和远程的都可以。
(node2@10.0.0.22)4> RemotePid = pid(5888,45,0).
通过BIF函数is_process_alive/1判断一个函数是否还活着。但是这个函数只能判断本地进程,无法知道远程进程的情况。
可以通过BIF函数:erlang:process_info/1察看本地进程的运行信息,但是这个函数不能察看远程进程。
(node2@10.0.0.22)4> erlang:process_info(Pid).
可以通过pid直接给远程节点上的进程发送消息:
(node2@10.0.0.22)4> pid(5888, 45, 0) ! {"hi", self()}.
(node2@10.0.0.22)5> flush().
Shell got {"hi",<0.147.0>}
](node2@10.0.0.22)6> RemotePid ! {"hello", self()}.
(node2@10.0.0.22)7> flush().
Shell got {"hello",<0.147.0>}
4. 将函数作为消息发送
接着玩个小把戏。在FP中,函数和atom、整数、字符串等一样都是数据。这意外着我们可以像发送atom、字符串等一样将本地函数作为消息发送到另外一个节点上,然后执行。
首先机器(ip地址是10.0.0.11)启动节点1,执行如下命令:
erl -name node1@10.0.0.11 -setcookie abc
然后在erl中定义接收消息的函数:
(node1@10.0.0.11)1> F1 = fun()->
(node1@10.0.0.11)1> receive
(node1@10.0.0.11)1> Fun-> io:format("I received !!!~n"), Fun()
(node1@10.0.0.11)1> end
(node1@10.0.0.11)1> end.
注意该函数只接收一条消息
创建并登记进程:
register(test1, spawn(fun() -> F1() end)).
在另外一台机器(ip地址是10.0.0.12)上启动节点2:
erl -name node2@10.0.0.12 -setcookie abc
然后定义作为消息发送出去的函数:
(node2@10.0.0.12)1> F2 = fun() -> io:format("HELLO WORLD~n") end.
将该函数发送到节点1上:
(node2@10.0.0.12)2> {test1, 'node1@10.0.0.11'} ! F2.
可以在节点1看到收到F2并执行的结果。
这样任何一个函数都可以发布到任何网络中的一个节点上执行,并不一定非得在定义它的地方执行。
函数作为一种数据可以作为消息发布。对模块而言,erl提供了BIF在各个节点间发布模块,这些BIF在
c模块中,主要有这两个
- c:nl(Module) 将在所有当前连接的节点中加载模块
- c:nc(Module) 编译模块,随后在所有连接的节点中加载模块
关于erlang模块的热更新
一个模块热更新的例子
运行时更新代码的问题:传统的系统比较难以在运行时更新代码,一般都是停机,替换代码,重新启动完成系统的升级。Erlang号称提供热切换的特性,也就是说在系统不停机时就能更新部分代码,很神奇的样子。热切换机制也与FP函数的这种特点有关,函数与普通对象没有本质的区别,那么既然运行时修改对象不算什么问题,动态更新函数也就是理所当然的了。
由于Erlang变量的不可变性,但是函数可以参数的形式实现动态变化:
loop(Fun) ->
receive
{execute, Arg} ->
Fun(Arg),
loop(Fun);
{update_fun, New_Fun} ->
loop(New_Fun)
end.
当某线程运行此段代码后,该线程就会一直接收别的线程发消息给它,如果收到{execute, Arg}消息,将执行Fun函数,完成相关业务处理;处理完后线程继续等待接收新的消息;
如果要不停机更新代码,就给该进程发送{update_fun, NewFun}消息,NewFun即为要更新的函数。
另一个模块热更新的例子
loop(Fun) ->
receive
{execute, Arg} ->
Fun(Arg),
?MODULE:loop(Fun)
end
当这个模块被重新加载后,再接到一次消息后会自动完成新模块的更新
分享到:
相关推荐
本文将详细讲解如何使用易语言来实现远程进程DLL函数的调用,这对于开发跨进程通信或者增强程序功能至关重要。 易语言是一款以“易”为理念的编程工具,它具有简洁的语法和丰富的内置功能,适合初学者和专业人士...
在操作系统中,进程是程序执行时的一个实例,它包括程序代码、数据、内存分配以及一个或多个线程。每个进程都有自己的地址空间,与其他进程隔离运行,以保证系统稳定和安全。 1. **强力杀进程**:在某些情况下,...
2. 调用`EnumProcessModules`函数,传入之前获取的进程句柄,以及一个模块句柄数组来存储进程中的所有模块。这个函数会返回成功列举的模块数量。 3. 通过`GetModuleBaseAddress`函数,你可以根据模块句柄获取模块的...
综合以上,易语言隐藏所有进程模块的源码涉及到了Windows系统底层编程、进程管理和内存操作,以及日志记录等技术。对于学习易语言和系统编程的开发者来说,这是一个很好的实践案例,有助于理解Windows内部机制,并...
在IT安全领域,PCHunter是一款备受专业人士推崇的工具,它主要用于查看进程模块以及检测DLL(动态链接库)注入现象,同时也是一种手动清除木马病毒的有效手段。本文将详细介绍PCHunter的功能、工作原理以及如何利用...
本报告详细分析了LINUX的消息函数,包括它们的主要功能、子模块以及相关数据结构。以下是关于这些函数的深入解析: 1. **课设简介** 课程设计的目的是理解并实现Linux操作系统中的消息队列功能。小组成员分工协作...
`ReadProcessMemory`函数**:虽然这不是实现模块隐藏的直接工具,但它经常与`WriteProcessMemory`一起使用,用于从目标进程的内存读取数据。在某些情况下,可能需要读取已写入的模块数据来验证其正确性或执行某些...
易语言是一种基于中文...综上所述,易语言隐藏所有进程模块的实现涉及多个层面的知识,包括进程和模块管理、内存操作、API调用、错误处理以及编程实践中的安全考量。掌握这些知识点,将有助于你理解和编写这样的源码。
2. **进程查找**:模块可能提供函数或方法来根据进程名称或PID查找特定进程。这涉及到操作系统级别的API调用,如Windows API中的`EnumProcesses`和`OpenProcess`函数。 3. **进程终止**:终止进程通常需要调用系统...
枚举进程内模块是编程中一个常见的任务,它允许程序员获取正在运行的进程所加载的所有动态链接库(DLL)或其他模块的信息。在Windows操作系统中,这个功能通常通过API调用来实现。 "易语言"是中国本土开发的一款...
本文将深入探讨如何使用VC++来枚举一个进程中的所有模块信息,以及这些信息在服务管理和系统分析中的应用。 首先,我们需要理解什么是进程模块。在Windows操作系统中,一个进程可以包含多个模块,这些模块可以是可...
在Windows操作系统中,我们可以使用如`EnumProcessModules`和`GetModuleInformation`这样的API函数来遍历并获取进程中的模块信息。 描述中提到的几个关键函数和概念如下: 1. **GetDword**:这是一个通用术语,...
1. **`CreateToolhelp32Snapshot`**:此函数用于创建一个快照,捕获系统当前的进程列表或模块列表。参数`TH32CS_SNAPPROCESS`表示我们将捕获所有进程的信息。 2. **`Process32First`与`Process32Next`**:这两个...
- 模块:这个压缩包提供的模块可能包含了一些封装好的函数,简化了窗口句柄和进程名的相互转换过程,提高了代码的可读性和易用性。 - 例程:例程通常是一段演示如何使用这些功能的代码,可以帮助开发者快速理解和...
1. **加载API**:易语言通过“外部函数”模块来调用操作系统API,例如LoadLibrary和GetProcAddress函数加载和获取隐藏进程所需的API地址。 2. **创建隐藏进程**:使用CreateProcess函数,并设置适当的标志,如CREATE...
本文将深入探讨如何根据进程名称在系统进程中找到指定的进程及其模块,主要涉及的知识点包括“进程名称”、“进程id”以及“进程模块”。 首先,我们要了解什么是进程。在操作系统中,进程是程序的执行实例,它包含...
也有可能包含有解释如何编写和调试内核模块的教程,以及如何分析和利用进程模块信息来进行系统优化或安全审计的实践案例。 总之,进程模块是操作系统的核心组成部分,理解其工作原理对于深入学习操作系统、软件开发...
3. **模块遍历**:除了遍历进程,还需要了解目标进程中的模块。模块可以是进程加载的动态链接库(DLL),它们提供了进程的功能。`EnumProcessModules`和`GetModuleFileName`等API可以帮助我们获取这些信息。 4. **...
消息函数通过消息队列的方式来实现消息传递,消息队列是进程之间互相发送消息的一种异步方式。 消息函数的主模块功能描述 ------------------------ 消息函数的主模块是负责管理消息队列的核心组件。该模块提供了...