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

Posted

技术标签:

【中文标题】有人可以解释 Erlang 中 Pid(进程标识符)的结构吗?【英文标题】:Can someone explain the structure of a Pid (Process Identifier) in Erlang? 【发布时间】:2010-09-19 14:12:39 【问题描述】:

谁能解释一下 Erlang 中 Pid 的结构?

Pids 看起来像这样:<A.B.C>,例如<0.30.0> ,但我想知道这三个“位”是什么意思:ABC

A 在本地节点上似乎总是0,但是当 Pid 的所有者位于另一个节点上时,此值会发生变化。

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

【问题讨论】:

好的,我的主要问题已经解决了。我只是没有将好的 pid 发送到远程端...... 【参考方案1】:

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

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

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 并返回其字符串表示形式。 感谢您提及 list_to_pid - 正是我想要的。这里有更多关于它的信息(具体来说,你不能将它与外部 pid 一起使用:***.com/questions/10475321/…) 仅供参考,这匹配:Pid = pid(0,123,0), Pid = list_to_pid("&lt;0.123.0&gt;").(18 日测试)【参考方案2】:

除了其他人所说的之外,您可能会发现这个简单的实验有助于了解内部发生的情况:

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 中。更多信息请参阅 Learn You Some Erlang 的 this section。

【讨论】:

【参考方案3】:

打印的进程ID由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 稍大一些,因为它们包括节点原子以及其他信息。 (Distributed PID format)

当一个内部 PID 从一个节点发送到另一个节点时,它会自动转换为外部/分布式 PID 形式,因此一个节点上的 &lt;0.10.0&gt; (inet_db) 可能会在以下情况下以 &lt;2265.10.0&gt; 结尾发送到另一个节点。您可以照常发送到这些 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()]). 

欲了解更多信息,请参阅:Internal PID structure, Node creation information, Node creation counter interaction with EPMD

【讨论】:

仔细查看源代码后发现创建计数器是错误的。感谢 Wallentin 促使我这样做。我现在确定 B 和 C 的位大小,但没有完全遵循 erts 源中的 _GET_BITS 宏,所以不确定我是否对顶部和底部位是正确的。【参考方案4】:

进程id由以下组成:

A,节点 id 不是任意的,而是 dist_entry 中该节点的内部索引。 (它实际上是节点名称的原子槽整数。) B、进程索引,指proctab中的内部索引,(0 -> MAXPROCS)。 C,每次达到 MAXPROCS 时增加的序列号。

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

【讨论】:

【参考方案5】:

PID 指的是一个进程和一个节点表。因此,只有在您进行调用的节点中已知 PID 时,您才能直接向 PID 发送消息。

如果您从已经在运行进程的节点knows about 进行调用的节点,这可能会起作用。

【讨论】:

如果我在远程节点上发出“nodes()”,我的本地节点会出现,但我无法注册“远程 pid”,因为 list_to_pid 失败:“register(client,list_to_pid(” "))。"返回“错误参数”。我错过了什么吗? 您只能注册本地 pid - 要注册远程 pid,您需要使用全局注册模块(或滚动您自己的注册系统)。

以上是关于有人可以解释 Erlang 中 Pid(进程标识符)的结构吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Erlang 中将消息路由到 PID

Erlang 中的并发

在LINUX内核中,进程标识符PID为1,2 ,3,4,5的进程的名称是啥?基本功能是啥?

在 Erlang 中发送/接收消息(并发)

WIN7系统怎样查看PID标识符

BUPT复试专题—进程管理