有人能解释一下Erlang中Pid(进程标识符)的结构吗?

soat7uwm  于 2022-12-08  发布在  Erlang
关注(0)|答案(5)|浏览(162)

Can someone explain the structure of a Pid in Erlang?
Pids looks like this: <A.B.C> , e.g. <0.30.0> , but I would like to know what is the meaning of these three "bits": A , B and C .
A seems to be always 0 on a local node, but this value changes when the Pid's owner is located on another node.
Is it possible to directly send a message on a remote node using only the Pid? Something like that: <4568.30.0> ! Message , without having to explicitly specify the name of the registered process and the node name ( {proc_name, Node} ! Message )?

ntjbwcob

ntjbwcob1#

Printed process ids < A.B.C > are composed of 6:

  • A, the node number (0 is the local node, an arbitrary number for a remote node)
  • B, the first 15 bits of the process number (an index into the process table) 7
  • C, bits 16-18 of the process number (the same process number as B) 7

Internally, the process number is 28 bits wide on the 32 bit emulator. The odd definition of B and C comes from R9B and earlier versions of Erlang in which B was a 15bit process ID and C was a wrap counter incremented when the max process ID was reached and lower IDs were reused.
In the erlang distribution PIDs are a little larger as they include the node atom as well as the other information. (Distributed PID format)
When an internal PID is sent from one node to the other, it's automatically converted to the external/distributed PID form, so what might be <0.10.0> ( inet_db ) on one node might end up as <2265.10.0> when sent to another node. You can just send to these PIDs as normal.

% 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()]).

For more information see: Internal PID structure, Node creation information, Node creation counter interaction with EPMD

iklwldmw

iklwldmw2#

如果我没记错的话,格式是<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
biswetbf

biswetbf3#

进程标识< A.B.C >由以下内容组成:

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

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

llmtgqce

llmtgqce4#

PID引用一个进程和一个节点表。因此,只有当PID在执行调用的节点中已知时,才能将消息直接发送到PID。
如果执行调用的节点已经是运行进程的节点,则此操作可能会起作用。

xnifntxz

xnifntxz5#

Apart from what others have said, you may find this simple experiment useful to understand what is going on internally:

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>>

So, you can se that the node name is internally stored in the pid. More info in this section of Learn You Some Erlang.

相关问题