有人可以解释 Erlang 中 Pid 的结构吗?
Pids 看起来像这样:<A.B.C>
, eg <0.30.0>
,但我想知道这三个“位”的含义是什么A
:B
和C
。
A
似乎总是0
在本地节点上,但是当 Pid 的所有者位于另一个节点上时,此值会发生变化。
是否可以仅使用 Pid 在远程节点上直接发送消息?类似的东西:<4568.30.0> ! Message
,而不必显式指定注册进程的名称和节点名称( {proc_name, Node} ! Message
)?
打印的进程 ID <ABC> 由6组成:
在内部,进程号在 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 的交互
如果我没记错的话,格式是<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
进程id<ABC>组成:
2位的创建标签不显示在pid中,而是在内部使用,每次节点重启时都会增加。
PID 指的是一个进程和一个节点表。因此,您只能将消息直接发送到 PID,前提是它在您进行调用的节点中是已知的。
如果您从中进行调用的节点已经知道进程正在运行的节点,那么这可能会起作用。
除了其他人所说的之外,您可能会发现这个简单的实验有助于了解内部发生的情况:
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。