Quelqu'un peut-il expliquer la structure d'un Pid à Erlang?
Pids ressemble à ceci:<A.B.C>
, par exemple. <0.30.0>, mais j'aimerais savoir quelle est la signification de ces trois "bits": A, B et C.
'A' semble toujours être 0 sur un nœud local, mais cette valeur change lorsque le propriétaire du Pid est situé sur un autre nœud.
Est-il possible d'envoyer directement un message sur un nœud distant en utilisant uniquement le PID? Quelque chose comme ça: <4568.30.0>! Message, sans avoir à spécifier explicitement le nom du processus enregistré et le nom du noeud ({nom_proc, Node}! Message)?
Les identifiants de processus imprimés <A.B.C> sont composés de 6 :
En interne, le numéro de processus a une largeur de 28 bits sur l'émulateur 32 bits. La définition étrange de B et C provient de R9B et de versions antérieures d'Erlang dans lesquelles B était un ID de processus 15 bits et C était un compteur intégré incrémenté lorsque l'ID de processus maximum était atteint et que des ID inférieurs étaient réutilisés.
Dans la distribution erlang, les PID sont un peu plus grands car ils incluent l'atome du nœud ainsi que d'autres informations. ( Format PID distribué )
Lorsqu'un PID interne est envoyé d'un nœud à un autre, il est automatiquement converti au format PID externe/distribué. Par conséquent, ce qui pourrait être <0.10.0>
(inet_db
) sur un nœud peut se transformer en <2265.10.0>
lorsqu'il est envoyé à un autre nœud. Vous pouvez simplement envoyer à ces PID comme d'habitude.
% 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()]).
Pour plus d'informations, voir: Structure interne du PID , Informations sur la création de nœud , Interaction du compteur de création de nœud avec EPMD
Si je me souviens bien de cela, le format est <nodeid,serial,creation>
. 0 est le nœud actuel un peu comme un ordinateur a toujours le nom d’hôte "localhost" pour se référer à lui-même. Ceci est dû à l’ancienne mémoire, de sorte qu’il pourrait ne pas être difficile à 100%.
Mais oui. Vous pouvez construire le pid avec list_to_pid/1
par exemple.
PidString = "<0.39.0>",
list_to_pid(PidString) ! message.
Bien sûr. Vous utilisez simplement la méthode dont vous avez besoin pour construire votre PidString. Probablement écrire une fonction qui la génère et l'utiliser à la place de PidString comme ceci:
list_to_pid( make_pid_from_term({proc_name, Node}) ) ! message
L'identifiant de processus <A.B.C> est composé de:
La balise de création de 2 bits ne s'affiche pas dans le pid mais est utilisée en interne et augmente à chaque redémarrage du nœud.
Le PID fait référence à un processus et à une table de nœuds. Ainsi, vous ne pouvez envoyer un message directement à un PID que s'il est connu dans le noeud à partir duquel vous effectuez l'appel.
Il est possible que cela fonctionne si le noeud sur lequel vous appelez déjà connaît le noeud sur lequel le processus est en cours d'exécution.
Outre ce que d'autres ont dit, vous pouvez trouver cette expérience simple utile pour comprendre ce qui se passe en interne:
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>>
Donc, vous pouvez voir que le nom du noeud est stocké en interne dans le pid. Plus d'informations dans cette section de Learn You Some Erlang.