Process 모듈
Process 모듈
프로세스와 프로세스 사전(dictionary)으로 작업하기 위한 편의 함수들을 제공하는 모듈이에요. 이 모듈의 함수 외에도 Kernel 모듈이 프로세스와 관련된 몇 가지 기본 기능을 노출하고 자동 import 합니다.
Kernel.spawn/1,Kernel.spawn/3Kernel.spawn_link/1,Kernel.spawn_link/3Kernel.spawn_monitor/1,Kernel.spawn_monitor/3Kernel.self/0Kernel.send/2
이 모듈이 프로세스로 작업하는 저수준 편의 기능을 제공하긴 하지만, 개발자들은 보통 시스템을 구축할 때 Agent, GenServer, Registry, Supervisor, Task 같은 추상화를 쓰고, 정보 수집·종료 트랩·링크·모니터링에 이 모듈에 의존합니다.
출처: Process
본문
Aliases
Alias는 Erlang/OTP 24에서 도입된 기능이에요. alias는 메시지를 보내기 위해 PID를 가리키는 방법입니다. alias를 쓰는 장점은, alias된 프로세스가 여전히 실행 중이더라도 alias를 비활성화할 수 있다는 점이에요. 비활성화된 alias로 메시지를 보내면 아무 일도 일어나지 않습니다. 이렇게 해서 요청/응답 시나리오를 더 쉽게 구현할 수 있어요.
alias/0나 alias/1로 alias를 설정하고, PID처럼 send/2로 그 alias에 메시지를 보낼 수 있어요. alias를 비활성화하려면 unalias/1을 쓰면 됩니다. 비활성화된 alias로 메시지를 보내면 아무 일도 일어나지 않아요.
예를 들어 :ping 메시지를 기다리는 프로세스가 있다고 해 보죠.
def server do
receive do
{:ping, source_alias} ->
send(source_alias, :pong)
server()
end
end
이제 다른 프로세스가 이 프로세스에 ping을 보낼 수 있어요.
server = spawn(&server/0)
source_alias = Process.alias()
send(server, {:ping, source_alias})
receive do
:pong -> :pong
end
#=> :pong
이제 source_alias를 비활성화하고 다시 ping을 보내면, 서버가 send/2로 :pong 응답을 비활성화된 alias에 보내므로 어떤 응답도 받지 못해요.
Process.unalias(source_alias)
send(server, {:ping, source_alias})
receive do
:pong -> :pong
after
1000 -> :timeout
end
#=> :timeout
Erlang reference manual의 Process Aliases 섹션도 참고하세요.
타입(Types)
@type alias() :: reference()
@type alias_opt() :: :explicit_unalias | :reply
@type dest() ::
pid()
| port()
| (registered_name :: atom())
| {registered_name :: atom(), node()}
@type process_info_item() :: atom() | {:dictionary, term()}
@type process_info_result_item() :: {process_info_item(), term()}
@type spawn_opt() ::
:link
| :monitor
| {:monitor, :erlang.monitor_option()}
| {:priority, :low | :normal | :high}
| {:fullsweep_after, non_neg_integer()}
| {:min_heap_size, non_neg_integer()}
| {:min_bin_vheap_size, non_neg_integer()}
| {:max_heap_size, heap_size()}
| {:message_queue_data, :off_heap | :on_heap}
@type spawn_opts() :: [spawn_opt()]
alias()—alias/0이나alias/1이 반환하는 aliasdest()— 프로세스 목적지. 원격·로컬 PID, 로컬 포트, 로컬 등록 이름, 또는 다른 노드의 등록된 이름에 대한{registered_name, node}형태의 튜플
함수(Functions)
alias() (1.15.0부터)
@spec alias() :: alias()
프로세스 alias를 만듭니다. alias([:explicit_unalias])로 alias/1을 호출하는 것과 같아요. :erlang.alias/0도 참고하세요. 컴파일러에 의해 인라인 처리됩니다.
alias = Process.alias()
alias(options) (1.15.0부터)
@spec alias([alias_opt()]) :: alias()
프로세스 alias를 만듭니다. alias에 대한 자세한 내용은 모듈 문서를 참고하세요. :erlang.alias/1도 참고하세요. 컴파일러에 의해 인라인 처리됩니다.
alias = Process.alias([:reply])
alive?(pid)
@spec alive?(pid()) :: boolean()
주어진 프로세스가 로컬 노드에서 살아 있는지 알려줍니다. pid가 식별하는 프로세스가 살아 있다면(즉 종료 중이 아니고 아직 종료하지 않았다면) true를, 아니면 false를 반환합니다. pid는 로컬 노드에서 실행 중인 프로세스를 가리켜야 하며, 그렇지 않으면 ArgumentError가 발생합니다. 어떤 노드의 프로세스가 살아 있는지 확인하려면 :erpc 모듈을 쓸 수 있어요.
:erpc.call(node(pid), Process, :alive?, [pid])
컴파일러에 의해 인라인 처리됩니다.
cancel_timer(timer_ref, options \ [])
@spec 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)
@spec delete(term()) :: term() | nil
프로세스 사전에서 주어진 key를 삭제합니다. 프로세스 사전에서 key 아래에 있던 값을 반환하거나, key가 저장되어 있지 않았다면 nil을 반환합니다.
iex> Process.put(:comments, ["comment", "other comment"])
iex> Process.delete(:comments)
["comment", "other comment"]
iex> Process.delete(:comments)
nil
demonitor(monitor_ref, options \ [])
@spec 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)
@spec exit(pid(), term()) :: true
reason과 함께 pid에 종료 신호를 보냅니다. reason의 값에 따라 종료 동작이 달라집니다.
:normal이면,pid가 자기 자신(호출 프로세스)이 아닌 한 종료하지 않습니다. 자기 자신이면:normal이유로 종료해요. 종료를 트랩하고 있다면 종료 신호가{:EXIT, from, :normal}메시지로 변환되어 메시지 큐로 전달됩니다.:kill이면, 즉Process.exit(pid, :kill)이 호출되면, 트랩할 수 없는 종료 신호가pid에 보내져:killed이유로 무조건 종료합니다.- 다른 어떤 term이고
pid가 종료를 트랩하지 않으면,pid는 주어진reason으로 종료합니다. - 다른 어떤 term이고
pid가 종료를 트랩하면, 종료 신호가{:EXIT, from, reason}메시지로 변환되어 메시지 큐로 전달됩니다.
컴파일러에 의해 인라인 처리됩니다.
Kernel.exit/1과의 차이점
Kernel.exit/1과 Process.exit/2는 이름이 비슷하지만 기능은 매우 달라요. Kernel.exit/1은 현재 프로세스를 멈추려는 의도일 때 쓰고, Process.exit/2는 다른 프로세스에 종료 신호를 보내려는 의도일 때 써야 합니다. 또한 Kernel.exit/1은 try/1로 잡을 수 있지만, Process.exit/2는 종료 트랩으로만 처리할 수 있고 신호가 :kill과 다를 때만 가능합니다.
Process.exit(pid, :kill)
#=> true
flag(flag, value)
@spec flag(:error_handler, module()) :: module()
@spec flag(:max_heap_size, heap_size()) :: heap_size()
@spec flag(:message_queue_data, :off_heap | :on_heap) :: :off_heap | :on_heap
@spec flag(:min_bin_vheap_size, non_neg_integer()) :: non_neg_integer()
@spec flag(:min_heap_size, non_neg_integer()) :: non_neg_integer()
@spec flag(:priority, priority_level()) :: priority_level()
@spec flag(:save_calls, 0..10000) :: 0..10000
@spec flag(:sensitive, boolean()) :: boolean()
@spec flag(:trap_exit, boolean()) :: boolean()
호출 프로세스에 대해 주어진 flag를 value로 설정합니다. flag의 이전 값을 반환해요. :erlang.process_flag/2 참고. 컴파일러에 의해 인라인 처리됩니다.
flag(pid, flag, value)
@spec flag(pid(), :save_calls, 0..10000) :: 0..10000
주어진 프로세스 pid에 대해 주어진 flag를 value로 설정합니다. flag의 이전 값을 반환해요. pid가 로컬 프로세스가 아니면 ArgumentError를 던집니다. flag에 허용되는 값은 flag/2에서 허용되는 것의 부분 집합, 즉 :save_calls뿐입니다. :erlang.process_flag/3 참고. 컴파일러에 의해 인라인 처리됩니다.
get()
@spec get() :: [{term(), term()}]
프로세스 사전의 모든 키-값 쌍을 반환합니다. 컴파일러에 의해 인라인 처리됩니다.
get(key, default \ nil)
@spec get(term(), default :: term()) :: term()
프로세스 사전에서 주어진 key의 값을 반환하거나, key가 설정되지 않았다면 default를 반환합니다.
# 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()
@spec 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)
@spec get_keys(term()) :: [term()]
프로세스 사전에서 주어진 value를 가진 모든 키를 반환합니다. 컴파일러에 의해 인라인 처리됩니다.
get_label(pid \ self()) (1.20.0부터)
@spec get_label(pid()) :: term()
set_label/1이나 :proc_lib.set_label/1로 설정된 프로세스 pid의 라벨을 반환합니다. pid를 넘기지 않으면 현재 프로세스가 기본값입니다.
Process.set_label({:any, "term"})
Process.get_label()
#=> {:any, "term"}
설정되지 않았다면 nil을 반환합니다.
Process.get_label(pid)
#=> nil
group_leader()
@spec group_leader() :: pid()
호출 프로세스의 그룹 리더(group leader) PID를 반환합니다. 컴파일러에 의해 인라인 처리됩니다.
Process.group_leader()
#=> #PID<0.53.0>
group_leader(pid, leader)
@spec group_leader(pid(), leader :: pid()) :: true
주어진 pid의 그룹 리더를 leader로 설정합니다. 보통 특정 셸에서 시작된 프로세스가 :init이 아닌 그룹 리더를 가져야 할 때 쓰입니다. 컴파일러에 의해 인라인 처리됩니다.
hibernate(mod, fun_name, args)
@spec hibernate(module(), atom(), list()) :: no_return()
호출 프로세스를 "휴면(hibernation)" 상태로 둡니다. 메모리 할당이 가능한 한 줄어든 대기 상태가 되는데, 가까운 미래에 메시지를 받을 것 같지 않을 때 유용해요. :erlang.hibernate/3 참고. 컴파일러에 의해 인라인 처리됩니다.
info(pid)
@spec info(pid()) :: keyword() | nil
pid가 식별하는 프로세스에 대한 정보를 반환하거나, 프로세스가 살아 있지 않으면 nil을 반환합니다. 디버깅 정보로만 쓰세요. :erlang.process_info/1 참고.
info(pid, spec)
@spec info(pid(), process_info_item()) :: process_info_result_item() | nil
@spec info(pid(), [process_info_item()]) :: [process_info_result_item()] | nil
pid가 식별하는 프로세스에 대한 정보를 반환하거나, 프로세스가 살아 있지 않으면 nil을 반환합니다. :erlang.process_info/2 참고.
link(pid_or_port)
@spec link(pid() | port()) :: true
호출 프로세스와 주어진 항목(프로세스 또는 포트) 사이에 링크를 만듭니다. 링크는 양방향이에요. 연결된 프로세스는 unlink/1로 풀 수 있습니다. 이미 그런 링크가 있다면 두 프로세스 사이에는 하나의 링크만 있을 수 있으므로 아무것도 하지 않아요. 프로세스가 자기 자신에 링크를 만들려고 하면 아무 일도 일어나지 않습니다.
두 프로세스가 연결되면 각각 상대방으로부터 종료 신호를 받습니다(exit/2 참고). pid1과 pid2가 연결되어 있다고 해 보죠. pid2가 :normal이 아닌 다른 이유로 종료하고(이는 프로세스가 일을 마칠 때 쓰는 종료 이유이기도 함) pid1이 종료를 트랩하지 않으면(flag/2 참고), pid1은 pid2와 같은 이유로 종료하고, 다시 연결된 다른 모든 프로세스에 종료 신호를 내보냅니다. pid1이 종료를 트랩할 때의 동작은 exit/2에 설명되어 있어요. :erlang.link/1 참고. 컴파일러에 의해 인라인 처리됩니다.
list()
@spec 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)
@spec 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 메시지가 즉시 전달됩니다. link와 monitor의 예시 참고. :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}
monitor(item, options) (1.15.0부터)
@spec monitor(pid() | {name, node()} | name, [:erlang.monitor_option()]) ::
reference()
when name: atom()
호출 프로세스에서 주어진 item에 대한 모니터링을 시작합니다. monitor/1과 비슷하지만 item을 모니터링하는 방법을 커스터마이즈하는 옵션을 받습니다. 그 옵션에 대한 문서는 :erlang.monitor/3을 참고하세요. 컴파일러에 의해 인라인 처리됩니다.
pid =
spawn(fn ->
receive do
{:ping, source_alias} -> send(source_alias, :pong)
end
end)
#=> #PID<0.118.0>
ref_and_alias = Process.monitor(pid, alias: :reply_demonitor)
#=> #Reference<0.906660723.3006791681.40191>
send(pid, {:ping, ref_and_alias})
receive do: (msg -> msg)
#=> :pong
ref_and_alias = Process.monitor(pid, alias: :reply_demonitor)
#=> #Reference<0.906660723.3006791681.40191>
send(pid, {:ping, ref_and_alias})
receive do: (msg -> msg)
#=> {:DOWN, #Reference<0.906660723.3006791681.40191>, :process, #PID<0.118.0>, :noproc}
put(key, value)
@spec 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)
@spec read_timer(reference()) :: non_neg_integer() | false
send_after/3이 만든 타이머를 읽습니다. 결과가 정수이면 타이머가 만료될 때까지 남은 밀리초를 나타냅니다. 결과가 false이면 timer_ref에 해당하는 타이머를 찾지 못했다는 뜻인데, 타이머가 만료됐거나 이미 취소됐거나 timer_ref가 타이머에 대응한 적이 없기 때문일 수 있어요. 타이머가 만료되어 메시지를 보냈더라도 이 함수는 타임아웃 메시지가 목적지에 도착했는지는 알려주지 않습니다. 컴파일러에 의해 인라인 처리됩니다.
register(pid_or_port, name)
@spec register(pid() | port(), atom()) :: true
주어진 pid_or_port를 로컬 노드에서 주어진 name으로 등록합니다. name은 아톰이어야 하고, Kernel.send/2로 메시지를 보낼 때 PID/포트 식별자 대신 쓸 수 있어요. register/2는 다음 경우에 ArgumentError로 실패합니다.
- PID/Port가 로컬에 존재하지 않고 살아 있지 않을 때
- 이름이 이미 등록되어 있을 때
pid_or_port가 이미 다른name으로 등록되어 있을 때
다음 이름들은 예약되어 프로세스나 포트에 할당할 수 없습니다.
nilfalsetrue:undefined
Process.register(self(), :test)
#=> true
send(:test, :hello)
#=> :hello
send(:wrong_name, :hello)
** (ArgumentError) argument error
registered()
@spec registered() :: [atom()]
register/2로 등록된 이름들의 리스트를 반환합니다. 컴파일러에 의해 인라인 처리됩니다.
Process.register(self(), :test)
Process.registered()
#=> [:test, :elixir_config, :inet_db, ...]
send(dest, msg, options)
@spec send(dest, msg, [option]) :: :ok | :noconnect | :nosuspend
when dest: dest(), msg: any(), option: :noconnect | :nosuspend
주어진 dest에 메시지를 보냅니다. dest는 원격·로컬 PID, 로컬 포트, 로컬 등록 이름, 또는 다른 노드의 등록된 이름에 대한 {registered_name, node} 형태의 튜플일 수 있어요. 컴파일러에 의해 인라인 처리됩니다.
옵션:
:noconnect— 사용 시, 메시지 전송이 다른 노드로의 자동 연결을 요구한다면 메시지를 보내지 않고:noconnect를 반환합니다.:nosuspend— 사용 시, 메시지 전송이 발신자를 일시 중단(suspend)하게 한다면 메시지를 보내지 않고:nosuspend를 반환합니다.
그 외에는 메시지를 보내고 :ok를 반환합니다.
iex> Process.send({:name, :node_that_does_not_exist}, :hi, [:noconnect])
:noconnect
send_after(dest, msg, time, opts \ [])
@spec send_after(pid() | atom(), term(), non_neg_integer(), [option]) :: reference()
when option: {:abs, boolean()}
time 밀리초 후에 msg를 dest에 보냅니다. dest가 PID이면 로컬 프로세스의 PID여야 하며, 죽었든 살아 있든 상관없습니다. dest가 아톰이면 배달 시점에 조회되는 등록된 프로세스의 이름이어야 합니다. 이름이 프로세스를 가리키지 않아도 오류는 발생하지 않아요.
메시지는 즉시 보내지지 않습니다. 따라서 time이 0이어도 dest는 그 사이에 다른 메시지를 받을 수 있어요. 이 함수는 타이머 레퍼런스를 반환하며, read_timer/1로 읽거나 cancel_timer/1로 취소할 수 있습니다. 주어진 dest가 살아 있지 않은 PID이거나 그 PID가 종료하면 타이머는 자동으로 취소됩니다. dest가 아톰일 때는 타이머가 자동으로 취소되지 않는다는 점에 유의하세요(아톰 해석은 배달 시에 이루어지기 때문).
옵션:
:abs— (boolean)false이면time이 현재 단조 시간(monotonic time)에 상대적인 것으로 취급됩니다.true이면time은msg가dest에 배달되어야 하는 Erlang 단조 시간의 절대값입니다. Erlang 단조 시간과 기타 시간 관련 개념에 대해 더 읽으려면System모듈 문서를 보세요. 기본값false.
timer_ref = Process.send_after(pid, :hi, 1000)
set_label(label) (1.17.0부터)
@spec set_label(term()) :: :ok
현재 프로세스에 설명적인 term을 추가합니다. 그 term은 고유할 필요가 없으며 Observer와 크래시 로그에 표시됩니다. 이 라벨은 :queue_worker나 {:live_chat, user_id}처럼 주어진 역할에서 여러 프로세스 중 하나를 식별하는 데 유용할 수 있어요.
Process.set_label(:worker)
#=> :ok
Process.set_label({:any, "term"})
#=> :ok
sleep(timeout)
@spec sleep(timeout()) :: :ok
현재 프로세스를 주어진 timeout 동안 잡니다. timeout은 밀리초 단위 정수 또는 :infinity 아톰입니다. :infinity가 주어지면 현재 프로세스는 영원히 잠들고 메시지를 소비하거나 응답하지 않아요.
수면 한계(Sleeping limit)
Elixir v1.18 이전에는 sleep/1이 16#ffffffff, 즉 2^32-1보다 큰 정수 타임아웃 값을 받지 못했어요. Elixir v1.18부터는 임의로 큰 정수 값을 받습니다.
이 함수는 극도로 주의해서 쓰세요. Elixir에서 sleep/1을 쓸 거의 모든 상황에는, 메시지 전달로 같은 목표를 달성하는 더 정확하고 빠르며 정밀한 방법이 있을 가능성이 높아요.
예를 들어 프로세스가 어떤 동작을 수행하기를 기다리고 있다면, 그 동작의 진행 상황을 메시지로 전달하는 편이 낫습니다.
즉, 이렇게 하지 말고:
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)
@spec spawn((-> any()), spawn_opts()) :: pid() | {pid(), reference()}
주어진 옵션에 따라 주어진 함수를 spawn합니다. 결과는 주어진 옵션에 달려 있어요. 특히 옵션으로 :monitor가 주어지면 PID와 모니터 레퍼런스가 담긴 튜플을, 그렇지 않으면 spawn된 프로세스 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)
@spec spawn(module(), atom(), list(), spawn_opts()) :: pid() | {pid(), reference()}
주어진 옵션에 따라 모듈 mod의 함수 fun을, 주어진 args를 넘겨 spawn합니다. 결과는 주어진 옵션에 달려 있어요. 특히 :monitor 옵션이 주어지면 PID와 모니터 레퍼런스가 담긴 튜플을, 아니면 spawn된 프로세스 PID만 반환합니다. 추가 옵션도 받으며, 사용 가능한 옵션 목록은 :erlang.spawn_opt/4를 확인하세요. 컴파일러에 의해 인라인 처리됩니다.
unalias(alias) (1.15.0부터)
@spec unalias(alias()) :: boolean()
프로세스 alias를 명시적으로 비활성화합니다. alias가 현재 프로세스의 현재-활성 alias였다면 true를, 아니면 false를 반환합니다. alias에 대한 자세한 내용은 모듈 문서를 참고하세요. :erlang.unalias/1도 참고하세요. 컴파일러에 의해 인라인 처리됩니다.
alias = Process.alias()
Process.unalias(alias)
#=> true
unlink(pid_or_port)
@spec unlink(pid() | port()) :: true
호출 프로세스와 주어진 항목(프로세스 또는 포트) 사이의 링크를 제거합니다. 그런 링크가 없다면 아무것도 하지 않아요. pid_or_port가 존재하지 않으면 오류를 만들지 않고 그냥 아무것도 하지 않습니다. 이 함수의 반환값은 항상 true입니다. :erlang.unlink/1 참고. 컴파일러에 의해 인라인 처리됩니다.
unregister(name)
@spec unregister(atom()) :: true
PID 또는 포트 식별자와 연결된 등록된 name을 제거합니다. 이름이 어떤 PID나 포트에도 등록되어 있지 않으면 ArgumentError로 실패합니다. 컴파일러에 의해 인라인 처리됩니다.
Process.register(self(), :test)
#=> true
Process.unregister(:test)
#=> true
Process.unregister(:wrong_name)
** (ArgumentError) argument error
whereis(name)
@spec whereis(atom()) :: pid() | port() | nil
name 아래에 등록된 PID 또는 포트 식별자를 반환하거나, 이름이 등록되어 있지 않으면 nil을 반환합니다. :erlang.whereis/1 참고.
Process.register(self(), :test)
Process.whereis(:test)
#=> #PID<0.84.0>
Process.whereis(:wrong_name)
#=> nil
더 알아보기
GenServer— 서버 구현 behaviourAgent— 상태를 감싸는 프로세스 추상화Registry— 프로세스 이름 등록 저장소Supervisor— 감독 트리Task— 비동기·병렬 작업