この記事は、Elixir Advent Calendar 2023 シリーズ14 の17日目です
【本コラムは、3分で読め、3分で試せます】
piacere です、ご覧いただいてありがとございます
iexの裏で動いているプロセスを拾ってみます
プロセスのリストアップ
現在、生きているプロセスをリストアップします
iex> list = Process.list |> Enum.map(& {&1, Process.info(&1)})
[
{#PID<0.0.0>,
[
registered_name: :init,
current_function: {:init, :loop, 1},
initial_call: {:erl_init, :start, 2},
status: :waiting,
message_queue_len: 0,
links: [#PID<0.42.0>, #PID<0.44.0>, #PID<0.10.0>],
dictionary: [],
trap_exit: true,
error_handler: :error_handler,
priority: :normal,
group_leader: #PID<0.0.0>,
total_heap_size: 3196,
heap_size: 1598,
stack_size: 2,
reductions: 9495,
garbage_collection: [
max_heap_size: %{error_logger: true, kill: true, size: 0},
min_bin_vheap_size: 46422,
min_heap_size: 233,
fullsweep_after: 65535,
minor_gcs: 3
],
suspending: []
]},
{#PID<0.1.0>,
[
registered_name: :erts_code_purger,
current_function: {:erlang, :hibernate, 3},
initial_call: {:erts_code_purger, :start, 0},
status: :waiting,
message_queue_len: 0,
links: [],
dictionary: [],
trap_exit: true,
error_handler: :error_handler,
priority: :high,
group_leader: #PID<0.0.0>,
total_heap_size: 4,
heap_size: 4,
stack_size: 1,
reductions: 22482,
garbage_collection: [
max_heap_size: %{error_logger: true, kill: true, size: 0},
min_bin_vheap_size: 46422,
min_heap_size: 233,
fullsweep_after: 65535,
minor_gcs: 2
],
suspending: []
]}
…
:registered_name
のみ拾ってみます
iex> list |> Enum.map(& &1 |> elem(1) |> Keyword.get(:registered_name))
[:init, :erts_code_purger, nil, nil, nil, nil, nil, :socket_registry,
:erl_prim_loader, :logger, :application_controller, nil, nil, :kernel_sup,
:code_server, :inet_db, :rex, nil, :global_name_server, nil, nil,
:global_group, :file_server_2, :erl_signal_server, :standard_error_sup,
:standard_error, nil, :user_drv, :user, nil, nil, :kernel_refc,
:kernel_safe_sup, :logger_sup, :logger_handler_watcher, :logger_proxy, nil,
nil, nil, :elixir_sup, :elixir_config, :elixir_code_server, nil, nil,
IEx.Supervisor, IEx.Config, IEx.Broker, IEx.Pry, nil, nil, ...]
nil以外を拾います
iex> list |> Enum.map(& &1 |> elem(1) |> Keyword.get(:registered_name)) |> Enum.reject(& &1 == nil)
[:init, :erts_code_purger, :socket_registry, :erl_prim_loader, :logger,
:application_controller, :kernel_sup, :code_server, :inet_db, :rex,
:global_name_server, :global_group, :file_server_2, :erl_signal_server,
:standard_error_sup, :standard_error, :user_drv, :user, :kernel_refc,
:kernel_safe_sup, :logger_sup, :logger_handler_watcher, :logger_proxy,
:elixir_sup, :elixir_config, :elixir_code_server, IEx.Supervisor, IEx.Config,
IEx.Broker, IEx.Pry, Logger.Supervisor, :logger_std_h_default]
プロセスの詳細を調べる
拾ったプロセス名から、適当なプロセスをピックアップして、詳細を見てみます(ここでは :global_name_server
を選択しました)
iex> list |> Enum.filter(& &1 |> elem(1) |> Keyword.get(:registered_name) == :global_name_server)
[
{#PID<0.55.0>,
[
registered_name: :global_name_server,
current_function: {:gen_server, :loop, 7},
initial_call: {:proc_lib, :init_p, 5},
status: :waiting,
message_queue_len: 0,
links: [#PID<0.56.0>, #PID<0.57.0>, #PID<0.49.0>],
dictionary: [
rand_seed: {%{
bits: 58,
jump: #Function<3.34006561/1 in :rand.exsplus_jump>,
next: #Function<0.34006561/1 in :rand.exsss_next>,
type: :exsss,
uniform: #Function<1.34006561/1 in :rand.exsss_uniform>,
uniform_n: #Function<2.34006561/2 in :rand.exsss_uniform>
}, [94824658367563367 | 25895920018195810]},
"$initial_call": {:global, :init, 1},
"$ancestors": [:kernel_sup, #PID<0.47.0>],
creation_extension: 591010589673783296
],
trap_exit: true,
error_handler: :error_handler,
priority: :normal,
group_leader: #PID<0.46.0>,
total_heap_size: 1597,
heap_size: 987,
stack_size: 11,
reductions: 904,
garbage_collection: [
max_heap_size: %{error_logger: true, kill: true, size: 0},
min_bin_vheap_size: 46422,
min_heap_size: 233,
fullsweep_after: 65535,
minor_gcs: 2
],
suspending: []
]}
]
:global_name_server
は、下記に解説ある通り、Erlangノードの名前解決を司るサーバです
:global.register_name
や :global.whereis_name
を使った分散の要で、色々な遊び方があるのですが、これはまた別のコラムに預けるとします