Может кто-нибудь объяснить структуру Pid в Erlang? - PullRequest
63 голосов
/ 28 октября 2008

Может кто-нибудь объяснить структуру Пида в Эрланге?

Пидс выглядит так: <A.B.C>, например <0.30.0>, но я хотел бы знать, что означают эти три «бита»: A, B и C.

«A» на локальном узле всегда равно 0, но это значение изменяется, когда владелец Pid находится на другом узле.

Можно ли напрямую отправить сообщение на удаленный узел, используя только Pid? Примерно так: <4568.30.0>! Сообщение, без необходимости явно указывать имя зарегистрированного процесса и имя узла ({proc_name, Node}! Message)?

Ответы [ 5 ]

69 голосов
/ 04 ноября 2008

Печатные идентификаторы процесса состоят из 6 :

  • A, номер узла (0 является местным узел, произвольный номер для удаленного узла)
  • B, первые 15 бит номера процесса (индекс в таблице процессов) 7
  • C, биты 16-18 номера процесса (тот же номер процесса, что и у B) 7

Внутри 32-битного эмулятора номер процесса имеет ширину 28 бит. Нечетное определение B и C происходит от R9B и более ранних версий Erlang, в которых B был 15-битным идентификатором процесса, а C - счетчиком оберток, увеличенным при достижении максимального идентификатора процесса и повторном использовании более низких идентификаторов.

В PID распределения erlang немного больше, поскольку они включают атом узла, а также другую информацию. ( Распределенный PID формат )

Когда внутренний PID отправляется с одного узла на другой, он автоматически преобразуется во внешнюю / распределенную форму PID, поэтому значение, равное <0.10.0> (inet_db) на одном узле, может быть равно <2265.10.0>, когда отправлено на другой узел. Вы можете просто отправить эти идентификаторы как обычно.

% 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

13 голосов
/ 28 октября 2008

Если я правильно помню это, формат будет <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
8 голосов
/ 01 мая 2009

Идентификатор процесса состоит из:

  • A, идентификатор узла, который не является произвольным, но является внутренним индексом для этого узла в dist_entry. (На самом деле это целое число атомного слота для имени узла.)
  • B, индекс процесса, который относится к внутреннему индексу в proctab (0 -> MAXPROCS).
  • C, Последовательный, который увеличивается каждый раз, когда MAXPROCS был достигнут.

Тег создания из 2 битов не отображается в pid, но используется внутри и увеличивается при каждом перезапуске узла.

2 голосов
/ 28 октября 2008

PID относится к процессу и таблице узлов. Таким образом, вы можете отправить сообщение непосредственно в PID, только если оно известно в узле, с которого вы выполняете вызов.

Возможно, это сработает, если узел, с которого вы выполняете вызов, уже знает о узле, на котором выполняется процесс.

0 голосов
/ 16 февраля 2015

Помимо того, что сказали другие, вы можете найти этот простой эксперимент полезным, чтобы понять, что происходит внутри:

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.

...