欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

local pid and remote pid

程序员文章站 2024-02-22 15:47:42
...
pid 既可以代表本地的process,也可以代表其他节点即远程 process,因此pid ! Msg,既可以向本地节点又可以向其他节点发送消息。

如何来区分local pid和remote pid呢,让我们先看看pid具体包含哪些信息。
打印pid变量的时候,其为X.Y.Z格式的数据,其中X代表的便是本地节点或者其他node(其可以为一个索引,指向某个已知节点),Y为4字节 unsigned integer代表的是process id(***,max 32767),Z为4个字节,为Serial(当pid中Y到达32767时,Z则增加)。
具体的pid数据格式请参考:http://www.erlang.org/doc/apps/erts/erl_ext_dist.html#8.8

在分布式开发中,如果节点之间交互,涉及到pid,那么erlang会自动为我们进行local pid到remote pid的转化。具体请参看下例:
为了方便我们的观察,研究,我对kernel中的rpc模块作了一点小改动,添加了一些调试信息:
rpc.erl:
handle_call/3函数 Line 99添加:


io:format("rpc handle_call:[M:~p F:~p A:~p] From:~p~n", [Mod, Fun, Args, To]),


handle_info/2函数 Line 148添加:

io:format("rpc reply To: ~p Msg:~p~n", [To, Reply]),


do_call/3函数 Line 232

io:format("rpc docall: Node:~p self:~p~n", [Node, self()]),


添加完这三条打印信息,随后编译rpc,将rpc.beam放置在kernerl/ebin目录下。(修改前,相信你会把rpc.erl和rpc.beam都备份一下的)。

随后我们启动两个erlang shell:

Node A: erl -sname a
Node B: erl -sname b


在Node b中,我们register一个名叫proc_on_b的process:
([email protected])4> register(proc_on_b, spawn(fun() -> receive Msg -> Msg end end)).


在Node a中:
([email protected])7> rpc:call('[email protected]', erlang, whereis, [proc_on_b]).


查看屏幕的输出:
Node a:
([email protected])7> rpc docall: Node:'[email protected]' self:<0.35.0>
<5094.53.0>


Node b:
([email protected])5> rpc handle_call:[M:erlang F:whereis A:[proc_on_b]] From:{<6253.35.0>, #Ref<6253.0.0.79>}
([email protected])5> rpc reply To: {<6253.35.0>,#Ref<6253.0.0.79>} Msg:<0.53.0>


仔细的查看屏幕输出,在a中,显示的rpc调用process的pid为<0.35.0>,而在b中rpc module收到的From的pid为<6253.35.0>,这里erlang已经把a中的local pid转化成为b所使用的remote pid。这样,b节点可以方便的发送信息。同样a中收到的pid信息为<5094.53.0>,也是对b所返回的信息 Msg:<0.53.0>进行了转化。

是不是所有Node之间交互的pid都会进行转化呢?
我们再做下一个试验:
我们写一个模块,让其通过c:pid/3生成一个pid,然后返回给某个节点,看这个节点是否将这个pid进行了转化。
在b的某个模块(pid_test)中添加下面的函数:
get_pid() ->
c:pid(0, 2222, 1).


随后a中调用:
([email protected])10> rpc:call('[email protected]', pid_test, get_pid, []).
rpc docall: Node:'[email protected]' self:<0.35.0>

<5094.2222.1>

同样,b中的pid:<0.2222.1> 贝进行了转化。

对于global module,如果我们中间传递了local pid,在另一方显示的是remote pid。