web-dev-qa-db-fra.com

Quelqu'un peut-il expliquer la structure d'un Pid à Erlang?

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

63
jideel

Les identifiants de processus imprimés <A.B.C> sont composés de 6 :

  • A, le numéro du noeud (0 est le noeud local , Un nombre arbitraire pour un noeud distant) 
  • B, les 15 premiers bits du numéro de processus (un index dans la table de processus) 7
  • C, bits 16-18 du numéro de processus (le même numéro de processus que B) 7

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

69
archaelus

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
13
Jon Gretar

L'identifiant de processus <A.B.C> est composé de:

  • Un ID de nœud qui n'est pas arbitraire mais l'index interne de ce nœud dans dist_entry. (Il s'agit en fait de l'entier de l'emplacement de l'atome pour le nom du nœud.)
  • B, index de processus qui fait référence à l'index interne dans le proctab, (0 -> MAXPROCS).
  • C, Série qui augmente chaque fois que MAXPROCS est atteint.

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.

8
psyeugenic

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. 

2
Ruben

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.

0
nacmartin