Процесс
Удобства работы с процессами и словарем процессов.
Помимо функций, доступных в этом модуле, модуль Kernel экспонирует и автоматически импортирует некоторые базовые функциональности, связанные с процессами, доступные через следующие функции:
-
Kernel.spawn/1иKernel.spawn/3 -
Kernel.spawn_link/1иKernel.spawn_link/3 -
Kernel.spawn_monitor/1иKernel.spawn_monitor/3 -
Kernel.self/0 -
Kernel.send/2
Хотя этот модуль предоставляет удобные инструменты низкого уровня для работы с процессами, разработчики обычно используют абстракции, такие как Agent, GenServer, Registry, Supervisor и Task для построения своих систем и прибегают к этому модулю для получения информации, перехвата завершений, связей и мониторинга.
Краткое описание
Типы
- dest()
Назначение процесса.
- spawn_opt()
- spawn_opts()
Функции
- alive?(pid)
Указывает, жив ли данный процесс на локальном узле.
- cancel_timer(timer_ref, options \\ [])
Отменяет таймер, возвращённый функцией
send_after/3.- delete(key)
Удаляет заданный
keyиз словаря процессов.- demonitor(monitor_ref, options \\ [])
Отключает монитор, идентифицированный данным
reference.- exit(pid, reason)
Отправляет сигнал выхода с заданным
reasonпроцессуpid.- flag(flag, value)
Устанавливает заданный
flagвvalueдля вызывающего процесса.- flag(pid, flag, value)
Устанавливает заданный
flagвvalueдля данного процессаpid.- get()
Возвращает все пары ключ-значение в словаре процессов.
- get(key, default \\ nil)
Возвращает значение для заданного
keyв словаре процессов илиdefault, еслиkeyне задано.- get_keys()
Возвращает все ключи в словаре процессов.
- get_keys(value)
Возвращает все ключи в словаре процессов, имеющие заданное
value.- group_leader()
Возвращает PID лидера группы для вызывающего процесса.
- group_leader(pid, leader)
Устанавливает лидера группы для данного
pidвleader.- hibernate(mod, fun_name, args)
Переводит вызывающий процесс в состояние "спячки".
- info(pid)
Возвращает информацию о процессе, идентифицированном
pid, или возвращаетnilесли процесс не жив.- info(pid, spec)
Возвращает информацию о процессе, идентифицированном
pid, или возвращаетnilесли процесс не жив.- link(pid_or_port)
Создаёт связь между вызывающим процессом и данным элементом (процессом или портом).
- list()
Возвращает список PID, соответствующих всем текущим процессам на локальном узле.
- monitor(item)
Начинает мониторинг данного
itemиз вызывающего процесса.- put(key, value)
Хранит заданную пару
key-valueв словаре процессов.- read_timer(timer_ref)
Считывает таймер, созданный функцией
send_after/3.- register(pid_or_port, name)
Регистрирует данный
pid_or_portпод заданнымname.- registered()
Возвращает список имён, которые были зарегистрированы с помощью
register/2.- send(dest, msg, options)
Отправляет сообщение на заданное
dest.- send_after(dest, msg, time, opts \\ [])
Отправляет
msgвdestчерезtimeмиллисекунд.- sleep(timeout)
Заставляет текущий процесс заснуть на заданный
timeout.- spawn(fun, opts)
Запускает заданную функцию в соответствии с заданными параметрами.
- spawn(mod, fun, args, opts)
Запускает заданную функцию
funиз модуляmod, передавая заданныеargsв соответствии с заданными параметрами.- unlink(pid_or_port)
Удаляет связь между вызывающим процессом и заданным элементом (процессом или портом).
- unregister(name)
Удаляет зарегистрированное
name, связанное с идентификатором PID или порта.- whereis(name)
Возвращает PID или идентификатор порта, зарегистрированные под
nameилиnil, если имя не зарегистрировано.
Типы
dest()
dest() ::
pid()
| port()
| (registered_name :: atom())
| {registered_name :: atom(), node()} Назначение процесса.
Удаленный или локальный PID, локальный порт, локально зарегистрированное имя или кортеж в формате {registered_name, node} для зарегистрированного имени на другом узле.
spawn_opt()
spawn_opt() ::
:link
| :monitor
| {:priority, :low | :normal | :high}
| {:fullsweep_after, non_neg_integer()}
| {:min_heap_size, non_neg_integer()}
| {:min_bin_vheap_size, non_neg_integer()} spawn_opts()
spawn_opts() :: [spawn_opt()]
Функции
alive?(pid)
alive?(pid()) :: boolean()
Указывает, жив ли данный процесс на локальном узле.
Если процесс, идентифицированный pid, жив (то есть он не завершается и ещё не завершился), то эта функция возвращает true. В противном случае возвращает false.
pid должен ссылаться на процесс, работающий на локальном узле, иначе поднимается исключение ArgumentError.
Встроено компилятором.
cancel_timer(timer_ref, options \\ [])
cancel_timer(reference(), options) :: non_neg_integer() | false | :ok when options: [async: boolean(), info: boolean()]
Отменяет таймер, возвращённый функцией send_after/3.
Если результат — целое число, оно представляет собой оставшееся время в миллисекундах до истечения таймера.
Если результат — false, таймер, соответствующий timer_ref, не найден. Это может произойти либо потому, что таймер истек, либо потому, что он уже был отменён, либо потому, что timer_ref никогда не соответствовал таймеру.
Даже если таймер истек, и сообщение было отправлено, эта функция не сообщает вам, пришло ли сообщение о таймауте к месту назначения.
Встроено компилятором.
Параметры
-
:async- (boolean) когдаfalse, запрос на отмену является синхронным. Когдаtrue, запрос на отмену является асинхронным, что означает, что запрос на отмену таймера отправляется и:okвозвращается сразу. По умолчаниюfalse. -
:info- (boolean) нужно ли возвращать информацию о том, что таймер был отменён. Когда опция:asyncравнаfalseи:infoравнаtrue, возвращается целое число илиfalse(как описано выше). Если:asyncравнаfalseи:infoравнаfalse, возвращается:ok. Если:asyncравнаtrueи:infoравнаtrue, вызывающему функции отправляется сообщение в формате{:cancel_timer, timer_ref, result}(гдеresult- целое число илиfalseкак описано выше) при выполнении отмены. Если:asyncравнаtrueи:infoравнаfalse, сообщение не отправляется. По умолчаниюtrue.
delete(key)
delete(term()) :: term() | nil
Удаляет заданный key из словаря процесса.
Возвращает значение, которое находилось под key в словаре процесса, или nil если key не хранилось в словаре процесса.
Примеры
iex> Process.put(:comments, ["comment", "other comment"]) iex> Process.delete(:comments) ["comment", "other comment"] iex> Process.delete(:comments) nil
demonitor(monitor_ref, options \\ [])
demonitor(reference(), options :: [:flush | :info]) :: boolean()
Отключает мониторинг монитора, идентифицируемого заданным reference.
Если monitor_ref является ссылкой, полученной вызывающим процессом при вызове monitor/1, этот мониторинг отключается. Если мониторинг уже отключён, ничего не происходит.
Для получения дополнительной информации см. :erlang.demonitor/2.
Встроено компилятором.
Примеры
pid = spawn(fn -> 1 + 2 end) ref = Process.monitor(pid) Process.demonitor(ref) #=> true
exit(pid, reason)
exit(pid(), term()) :: true
Отправляет сигнал выхода с заданным reason процессу pid.
Следующее поведение применяется, если reason является любым термином, кроме :normal или :kill:
-
Если
pidне перехватывает выходы,pidзавершится с заданнымreason. -
Если
pidперехватывает выходы, сигнал выхода преобразуется в сообщение{:EXIT, from, reason}и передаётся в очередь сообщенийpid.
Если reason является атомом :normal, pid не завершится (если только pid не является вызывающим процессом, в этом случае он завершится с причиной :normal). Если он перехватывает выходы, сигнал выхода преобразуется в сообщение {:EXIT, from, :normal} и передаётся в его очередь сообщений.
Если reason является атомом :kill, то есть, если вызвана Process.exit(pid, :kill), сигнал непрерываемого выхода отправляется процессу pid, который безусловно завершится с причиной :killed.
Встроено компилятором.
Примеры
Process.exit(pid, :kill) #=> true
flag(flag, value)
flag(:error_handler, module()) :: module()
flag(:max_heap_size, heap_size()) :: heap_size()
flag(:message_queue_data, :erlang.message_queue_data()) :: :erlang.message_queue_data()
flag(:min_bin_vheap_size, non_neg_integer()) :: non_neg_integer()
flag(:min_heap_size, non_neg_integer()) :: non_neg_integer()
flag(:monitor_nodes, term()) :: term()
flag({:monitor_nodes, term()}, term()) :: term()
flag(:priority, priority_level()) :: priority_level()
flag(:save_calls, 0..10000) :: 0..10000
flag(:sensitive, boolean()) :: boolean()
flag(:trap_exit, boolean()) :: boolean()
Устанавливает заданный flag в value для вызывающего процесса.
Возвращает старое значение flag.
Для получения дополнительной информации см. :erlang.process_flag/2.
Встроено компилятором.
flag(pid, flag, value)
flag(pid(), :save_calls, 0..10000) :: 0..10000
Устанавливает заданный flag в value для заданного процесса pid.
Возвращает старое значение flag.
Выбрасывает ArgumentError, если pid не является локальным процессом.
Допустимые значения для flag — это только подмножество значений, разрешенных в flag/2, а именно :save_calls.
Для получения дополнительной информации см. :erlang.process_flag/3.
Встроено компилятором.
get()
get() :: [{term(), term()}] Возвращает все пары ключ-значение в словаре процесса.
Встроено компилятором.
get(key, default \\ nil)
get(term(), default :: term()) :: term()
Возвращает значение для заданного key в словаре процесса, или default если key не задано.
Примеры
# Assuming :locale was not set iex> Process.get(:locale, "pt") "pt" iex> Process.put(:locale, "fr") nil iex> Process.get(:locale, "pt") "fr"
get_keys()
get_keys() :: [term()]
Возвращает все ключи в словаре процесса.
Встроено компилятором.
Примеры
# Assuming :locale was not set iex> :locale in Process.get_keys() false iex> Process.put(:locale, "pt") nil iex> :locale in Process.get_keys() true
get_keys(value)
get_keys(term()) :: [term()]
Возвращает все ключи в словаре процесса, которые имеют заданное value.
Встроено компилятором.
group_leader()
group_leader() :: pid()
Возвращает PID лидера группы для вызывающего процесса.
Встроено компилятором.
Примеры
Process.group_leader() #=> #PID<0.53.0>
group_leader(pid, leader)
group_leader(pid(), leader :: pid()) :: true
Устанавливает лидера группы для данного pid в leader.
Обычно используется, когда процесс, запущенный из определённой оболочки, должен иметь лидера группы, отличного от :init.
Встроено компилятором.
hibernate(mod, fun_name, args)
hibernate(module(), atom(), list()) :: no_return()
Переводит вызывающий процесс в состояние «спячки».
Вызывающий процесс переводится в состояние ожидания, где его выделение памяти уменьшено по возможности, что полезно, если процесс не ожидает получить сообщения в ближайшее время.
Для получения дополнительной информации см. :erlang.hibernate/3.
Встроено компилятором.
info(pid)
info(pid()) :: keyword() | nil
Возвращает информацию о процессе, идентифицируемом pid, или возвращает nil, если процесс не активен.
Используйте только для отладки.
Для получения дополнительной информации см. :erlang.process_info/1.
info(pid, spec)
info(pid(), atom() | [atom()]) :: {atom(), term()} | [{atom(), term()}] | nil Возвращает информацию о процессе, идентифицируемом pid, или возвращает nil, если процесс не активен.
Для получения дополнительной информации см. :erlang.process_info/2.
link(pid_or_port)
link(pid() | port()) :: true
Создаёт связь между вызывающим процессом и заданным элементом (процессом или портом).
Связи двусторонние. Связанные процессы могут быть разъединены с помощью unlink/1.
Если такая связь уже существует, эта функция ничего не делает, так как между двумя заданными процессами может быть только одна связь. Если процесс пытается создать связь с самим собой, ничего не произойдёт.
Когда два процесса связаны, каждый из них получает сигналы выхода от другого (см. также exit/2). Предположим, что pid1 и pid2 связаны. Если pid2 завершается с причиной, отличной от :normal (которая также является причиной выхода, когда процесс завершает свою работу), и pid1 не перехватывает выходы (см. flag/2), то pid1 завершится с той же причиной, что и pid2 и, в свою очередь, отправит сигнал выхода всем своим другим связанным процессам. Поведение, когда pid1 перехватывает выходы, описано в exit/2.
Для получения дополнительной информации см. :erlang.link/1.
Встроено компилятором.
list()
list() :: [pid()]
Возвращает список PID, соответствующих всем процессам, которые в настоящее время существуют на локальном узле.
Обратите внимание, что если процесс завершается, он считается существующим, но не активным. Это означает, что для такого процесса alive?/1 вернёт false, но его PID будет частью списка PID, возвращённого этой функцией.
Для получения дополнительной информации см. :erlang.processes/0.
Встроено компилятором.
Примеры
Process.list() #=> [#PID<0.0.0>, #PID<0.1.0>, #PID<0.2.0>, #PID<0.3.0>, ...]
monitor(item)
monitor(pid() | {name, node()} | name) :: reference() when name: atom() Начинает мониторинг заданного item из вызывающего процесса.
После завершения отслеживаемого процесса процессу-наблюдателю в виде сообщения:
{:DOWN, ref, :process, object, reason} где:
-
ref— ссылка на монитор, возвращаемая этой функцией; -
object— это либоpidотслеживаемого процесса (если отслеживается PID), либо{name, node}(если отслеживается удалённое или локальное имя); -
reason— причина выхода.
Если процесс уже завершён при вызове Process.monitor/1, сообщение :DOWN доставляется немедленно.
См. необходимость мониторинга для примера. См. :erlang.monitor/2 для получения дополнительной информации.
Вставлено компилятором.
Примеры
pid = spawn(fn -> 1 + 2 end)
#=> #PID<0.118.0>
Process.monitor(pid)
#=> #Reference<0.906660723.3006791681.40191>
Process.exit(pid, :kill)
#=> true
receive do
msg -> msg
end
#=> {:DOWN, #Reference<0.906660723.3006791681.40191>, :process, #PID<0.118.0>, :noproc} put(key, value)
put(term(), term()) :: term() | nil
Сохраняет заданную пару key-value в словаре процесса.
Возвращаемое значение этой функции — значение, которое ранее хранилось по ключу key, или nil, если значение по этому ключу не хранилось.
Примеры
# Assuming :locale was not set iex> Process.put(:locale, "en") nil iex> Process.put(:locale, "fr") "en"
read_timer(timer_ref)
read_timer(reference()) :: non_neg_integer() | false
Считывает таймер, созданный с помощью send_after/3.
Если результат — целое число, оно представляет собой время в миллисекундах, оставшееся до истечения таймера.
Если результат — false, таймер, соответствующий timer_ref, не найден. Это может быть из-за истечения таймера, его отмены или того, что timer_ref никогда не соответствовал таймеру.
Даже если таймер истек, а сообщение было отправлено, эта функция не сообщает вам, дошло ли сообщение о таймауте до пункта назначения.
Вставлено компилятором.
register(pid_or_port, name)
register(pid() | port(), atom()) :: true
Регистрирует данный pid_or_port под данным name.
name должно быть атомом и может использоваться вместо идентификатора PID/порта при отправке сообщений с помощью Kernel.send/2.
register/2 завершится ошибкой ArgumentError в следующих случаях:
- PID/порт не существует локально и не активен
- имя уже зарегистрировано
pid_or_portуже зарегистрирован под другимname
Следующие имена зарезервированы и не могут быть назначены процессам или портам:
-
nil -
false -
true -
:undefined
Примеры
Process.register(self(), :test) #=> true send(:test, :hello) #=> :hello send(:wrong_name, :hello) #=> ** (ArgumentError) argument error
registered()
registered() :: [atom()]
Возвращает список имён, зарегистрированных с помощью register/2.
Вставлено компилятором.
Примеры
Process.register(self(), :test) Process.registered() #=> [:test, :elixir_config, :inet_db, ...]
send(dest, msg, options)
send(dest, msg, [option]) :: :ok | :noconnect | :nosuspend when dest: dest(), msg: any(), option: :noconnect | :nosuspend
Отправляет сообщение указанному dest.
dest может быть удалённым или локальным PID, локальным портом, локально зарегистрированным именем или кортежем в форме {registered_name, node} для зарегистрированного имени на другом узле.
Вставлено компилятором.
Опции
-
:noconnect- при использовании, если отправка сообщения потребует автоматического подключения к другому узлу, сообщение не отправляется и возвращается:noconnect. -
:nosuspend- при использовании, если отправка сообщения приведет к приостановке отправителя, сообщение не отправляется и возвращается:nosuspend.
В противном случае сообщение отправляется и возвращается :ok.
Примеры
iex> Process.send({:name, :node_that_does_not_exist}, :hi, [:noconnect])
:noconnect send_after(dest, msg, time, opts \\ [])
send_after(pid() | atom(), term(), non_neg_integer(), [option]) :: reference()
when option: {:abs, boolean()} Отправляет msg в dest через time миллисекунд.
Если dest является PID, это должен быть PID локального процесса, активного или завершённого. Если dest — атом, это должно быть имя зарегистрированного процесса, которое ищется во время доставки. Ошибка не возникает, если имя не ссылается на процесс.
Сообщение не отправляется сразу. Поэтому dest может получать другие сообщения между отправкой, даже когда time является 0.
Эта функция возвращает идентификатор таймера, который можно прочитать с помощью read_timer/1 или отменить с помощью cancel_timer/1.
Таймер будет автоматически отменён, если указанный dest — PID, который не активен, или когда указанный PID завершается. Обратите внимание, что таймеры не будут автоматически отменены, когда dest — атом (так как разрешение атома выполняется при доставке).
Вставлено компилятором.
Опции
-
:abs- (логическое значение) когдаfalse,timeрассматривается как относительное к текущему монотонному времени. Когдаtrue,time— абсолютное значение эрланговского монотонного времени, в котороеmsgдолжен быть доставленdest. Чтобы узнать больше о монотонном времени Erlang и других связанных с временем понятиях, см. документацию для модуляSystem. По умолчаниюfalse.
Примеры
timer_ref = Process.send_after(pid, :hi, 1000)
sleep(timeout)
sleep(timeout()) :: :ok
Процесс спит заданное timeout.
timeout — это либо количество миллисекунд сна в виде целого числа, либо атом :infinity. Когда :infinity указан, текущий процесс спит вечно и не потребляет или не отвечает на сообщения.
Используйте эту функцию с большой осторожностью. Почти во всех ситуациях, где вы бы использовали sleep/1 в Elixir, скорее всего, существует более правильный, быстрый и точный способ достижения того же с помощью обмена сообщениями.
Например, если вы ждёте, что процесс выполнит некоторое действие, лучше передавать прогресс этого действия с помощью сообщений.
Другими словами, не:
Task.start_link(fn -> do_something() ... end) # Wait until work is done Process.sleep(2000)
А делайте:
parent = self() Task.start_link(fn -> do_something() send(parent, :work_is_done) ... end) receive do :work_is_done -> :ok after # Optional timeout 30_000 -> :timeout end
В таких случаях, как выше, предпочтительнее использовать Task.async/1 и Task.await/2.
Аналогично, если вы ждёте завершения процесса, отслеживайте этот процесс вместо сна. Не:
Task.start_link(fn -> ... end) # Wait until task terminates Process.sleep(2000)
А делайте:
{:ok, pid} =
Task.start_link(fn ->
...
end)
ref = Process.monitor(pid)
receive do
{:DOWN, ^ref, _, _, _} -> :task_is_down
after
# Optional timeout
30_000 -> :timeout
end spawn(fun, opts)
spawn((() -> any()), spawn_opts()) :: pid() | {pid(), reference()} Запускает данную функцию в соответствии с заданными параметрами.
Результат зависит от заданных параметров. В частности, если :monitor задан в качестве параметра, он вернёт кортеж, содержащий PID и ссылку на мониторинг, в противном случае только PID запущенного процесса.
Дополнительные параметры доступны; для получения полного списка доступных параметров см. :erlang.spawn_opt/4.
Вставлено компилятором.
Примеры
Process.spawn(fn -> 1 + 2 end, [:monitor])
#=> {#PID<0.93.0>, #Reference<0.18808174.1939079169.202418>}
Process.spawn(fn -> 1 + 2 end, [:link])
#=> #PID<0.95.0> spawn(mod, fun, args, opts)
spawn(module(), atom(), list(), spawn_opts()) :: pid() | {pid(), reference()} Запускает указанную функцию fun из модуля mod, передавая указанные args в соответствии с заданными параметрами.
Результат зависит от заданных параметров. В частности, если :monitor задан в качестве параметра, он вернёт кортеж, содержащий PID и ссылку на мониторинг, в противном случае только PID запущенного процесса.
Также принимаются дополнительные параметры; для получения списка доступных параметров см. :erlang.spawn_opt/4.
Вставлено компилятором.
unlink(pid_or_port)
unlink(pid() | port()) :: true
Удаляет связь между вызывающим процессом и заданным элементом (процессом или портом).
Если такой связи нет, эта функция ничего не делает. Если pid_or_port не существует, эта функция не генерирует ошибок и просто ничего не делает.
Возвращаемое значение этой функции всегда true.
См. :erlang.unlink/1 для получения дополнительной информации.
Вставлено компилятором.
unregister(name)
unregister(atom()) :: true
Удаляет зарегистрированное name, связанное с идентификатором PID или порта.
Возвращает ошибку ArgumentError, если имя не зарегистрировано ни для какого PID или порта.
Вставлено компилятором.
Примеры
Process.register(self(), :test) #=> true Process.unregister(:test) #=> true Process.unregister(:wrong_name) #=> ** (ArgumentError) argument error
whereis(name)
whereis(atom()) :: pid() | port() | nil
Возвращает идентификатор PID или порта, зарегистрированный под name, или nil, если имя не зарегистрировано.
См. :erlang.whereis/1 для получения дополнительной информации.
Примеры
Process.register(self(), :test) Process.whereis(:test) #=> #PID<0.84.0> Process.whereis(:wrong_name) #=> nil
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.8.2/Process.html