有人可以用Erlang解释Pid(进程标识符)的结构吗?


70

有人可以用Erlang解释Pid的结构吗?

点看起来像这样:<A.B.C>,例如<0.30.0>,但是我想知道这三个“位”(A,B和C)的含义是什么。

“ A”在本地节点上似乎始终为0,但是当Pid的所有者位于另一个节点上时,此值会更改。

是否可以仅使用Pid在远程节点上直接发送消息?像这样:<4568.30.0>!消息,而不必显式指定已注册进程的名称和节点名称({proc_name,Node}!消息)?


好的,我的主要问题已经解决。我只是没有将好的pid发送到远端...
jideel

Answers:


78

打印的进程ID <ABC>由6组成:

  • A,节点号(0是本地节点,对于远程节点是任意数字)
  • B,进程号的前15位(进入进程表的索引)7
  • C,过程编号的位16-18(与B相同的过程编号)7

在内部,在32位仿真器上,进程号为28位宽。B和C的奇怪定义来自R9B和早期版本的Erlang,其中B是15位进程ID,而C是当达到最大进程ID并重用了较低ID时递增的换行计数器。

在Erlang分布中,PID稍大一些,因为它们包括节点原子以及其他信息。(分布式PID格式

当内部PID从一个节点发送到另一个节点时,它会自动转换为外部/分布式PID形式,因此一个节点上的<0.10.0>inet_db)可能最终会像<2265.10.0>发送到另一节点时一样结束。您可以正常发送给这些PID。

% get the PID of the user server on OtherNode
RemoteUser = rpc:call(OtherNode, erlang,whereis,[user]), 

true = is_pid(RemoteUser),

% send message to remote PID
RemoteUser ! ignore_this, 

% print "Hello from <nodename>\n" on the remote node's console.
io:format(RemoteUser, "Hello from ~p~n", [node()]). 

有关更多信息,请参见:内部PID结构节点创建信息节点创建计数器与EPMD的交互


1
事实证明,在仔细查看源代码之后,我对创建计数器是错误的。感谢Wallentin提示我这样做。我现在可以确定B和C的位大小,但是并没有完全遵循erts源代码中的_GET_BITS宏,因此不确定我是否正确。
archaelus

13

如果我没记错的话,格式是<nodeid,serial,creation>。0是当前节点,就像计算机始终使用主机名“ localhost”来引用自身一样。这是由旧的记忆造成的,因此可能不是100%正确的解决方案。

但是,是的。例如,您可以使用构建pid list_to_pid/1

PidString = "<0.39.0>",
list_to_pid(PidString) ! message.

当然。您只需使用构建PidString所需的任何方法即可。大概编写一个生成它并使用它的函数,而不是像这样的PidString:

list_to_pid( make_pid_from_term({proc_name, Node}) ) ! message

您是否看到了这个大红色警告?list_to_pid / 1 而且您也可以简单地发送{proc_name,Node}!消息或使用模块全局(如果要使用全局名称)。
海尼克

是的。了解其他方法。这就是我所使用的。那不是问题。:)
乔恩·格雷塔尔

pid_to_list / 1获取一个pid并返回其字符串表示形式。
mcandre

感谢您提及list_to_pid-正是我想要的。以下是有关它的更多信息(特别是,您不能将其与外部pids一起使用:stackoverflow.com/questions/10475321/…
btk

仅供参考,该匹配项:(Pid = pid(0,123,0), Pid = list_to_pid("<0.123.0>").在18日测试)
鸦片

8

进程ID <ABC>由以下部分组成:

  • A,不是唯一的节点ID,而是dist_entry中该节点的内部索引。(它实际上是节点名称的原子插槽整数。)
  • B,进程索引,它引用proctab中的内部索引(0-> MAXPROCS)。
  • C,串行,每次达到MAXPROCS时增加。

2位的创建标记不会显示在pid中,而是在内部使用,并且在每次节点重新启动时都会增加。


3

PID是指进程和节点表。因此,如果您在进行调用的节点中知道消息,则只能直接将消息发送给PID。

如果您从中进行调用的节点已经知道运行该进程的节点,则可能会起作用。


1
如果我在远程节点上发出“ nodes()”,则会出现我的本地节点,但是我无法注册“ remote pid”,因为list_to_pid失败:“ register(client,list_to_pid(” <5058.95.0>“)) 。” 返回“错误参数”。我想念什么吗?
jideel

您只能注册本地pid-要注册远程pid,则需要使用全局注册模块(或使用自己的注册系统)。
archaelus

0

除了其他人说的话,您可能会发现这个简单的实验对于了解内部发生的事情很有用:

1> node().
nonode@nohost
2> term_to_binary(node()).
<<131,100,0,13,110,111,110,111,100,101,64,110,111,104,111,
  115,116>>
3> self().                
<0.32.0>
4> term_to_binary(self()).
<<131,103,100,0,13,110,111,110,111,100,101,64,110,111,104,
  111,115,116,0,0,0,32,0,0,0,0,0>>

因此,您可以确定节点名称在内部存储在pid中。本部分的“了解一些Erlang”中的更多信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.