erlinit が起動する beam.smp プロセスについて

[組込み Linux としての Nerves](https://qiita.com/pojiro/items/818affe535f3840b57fd) で調べきれなかった `erlinit` が起動する beam.smp プロセスについて調べました。

`erlinit`, PID 1, が起動するプロセス（スレッドを含む）群を `ps -wlT` で表示すると以下でした。

```elixir
S     0    72     1  2008   216 ttyS0 02:37 00:00:00 /usr/bin/nbtty /srv/erlang/erts-13.1.2/bin/erlexec -config /srv/erlang/release
S     0    80     1  5476   332 0:0   02:37 00:00:00 /usr/sbin/rngd
S     0    81    72  2008    80 0:0   02:37 00:00:00 /usr/bin/nbtty /srv/erlang/erts-13.1.2/bin/erlexec -config /srv/erlang/release
S     0    82    81 2497m  119m pts0  02:37 00:00:00 /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbwt none -sbwtdc
S     0    83    81 2497m  119m pts0  02:37 00:00:00 {sys_sig_dispatc} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    84    81 2497m  119m pts0  02:37 00:00:00 {sys_msg_dispatc} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    85    81 2497m  119m pts0  02:37 00:00:00 {async_1} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbwt no
S     0    88    81 2497m  119m pts0  02:37 00:00:00 {1_scheduler} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbw
S     0    89    81 2497m  119m pts0  02:37 00:00:00 {2_scheduler} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbw
S     0    90    81 2497m  119m pts0  02:37 00:00:00 {3_scheduler} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbw
R     0    91    81 2497m  119m pts0  02:37 00:00:01 {4_scheduler} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbw
S     0    92    81 2497m  119m pts0  02:37 00:00:00 {1_dirty_cpu_sch} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    93    81 2497m  119m pts0  02:37 00:00:00 {2_dirty_cpu_sch} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    94    81 2497m  119m pts0  02:37 00:00:00 {3_dirty_cpu_sch} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    95    81 2497m  119m pts0  02:37 00:00:00 {4_dirty_cpu_sch} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    96    81 2497m  119m pts0  02:37 00:00:00 {1_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    97    81 2497m  119m pts0  02:37 00:00:00 {2_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    98    81 2497m  119m pts0  02:37 00:00:00 {3_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0    99    81 2497m  119m pts0  02:37 00:00:00 {4_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0   100    81 2497m  119m pts0  02:37 00:00:00 {5_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0   101    81 2497m  119m pts0  02:37 00:00:00 {6_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0   102    81 2497m  119m pts0  02:37 00:00:00 {7_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0   103    81 2497m  119m pts0  02:37 00:00:00 {8_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0   104    81 2497m  119m pts0  02:37 00:00:00 {9_dirty_io_sche} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0   105    81 2497m  119m pts0  02:37 00:00:00 {10_dirty_io_sch} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp
S     0   106    81 2497m  119m pts0  02:37 00:00:00 {1_aux} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbwt none
S     0   107    81 2497m  119m pts0  02:37 00:00:00 {0_poller} /srv/erlang/erts-13.1.2/bin/beam.smp -Bc -C multi_time_warp -sbwt n
S     0    86    82  2144  1168 0:0   02:37 00:00:00 erl_child_setup 1024
```

これらは整理すると以下のように分類できました。
※プロセスかスレッドかの違いは `ps` の `-T` オプションを外して確認した。

- PID 72, PPID 1,  nbtty parent, プロセス
- PID 81, PPID 72, nbtty forked child, erlexec(Erlang runtime system)を実行する, プロセス
- PID 82, PPID 81, beam.smp, プロセス
- PID 83, PPID 81, {sys_sig_dispatc}, スレッド
- PID 84, PPID 81, {sys_msg_dispatc}, スレッド
- PID 85, PPID 81, {async_1}, スレッド
- PID 88,89,90,91, PPID 81, {1,2,3,4_scheduler}, スレッド
  - Schedulers, https://www.erlang.org/doc/man/erl.html#+S
- PID 92,93,94,95, PPID 81, {1,2,3,4_dirty_cpu_sch}, スレッド
  - Dirty CPU Schedulers, https://www.erlang.org/doc/man/erl.html#+SDcpu
- PID 96,97,98,99,100,101,102,103,104,105, PPID 81, {1,2,3,4,5,6,7,8,9,10_dirty_io_sch}, スレッド
  - Dirty IO Schedulers, https://www.erlang.org/doc/man/erl.html#+SDio
- PID 106, PPID 81, {1_aux}, スレッド
- PID 107, PPID 81, {0_poller}, スレッド
- PID 86, PPID 81, erl_child_setup 1024, プロセス

Erlang VM に関わるのは `nbtty` が `erlexec` を実行することで立ち上げている PPID が 81 の beam.smp プロセスとその他のスレッドです。

`erlexec` は Nerves でない場合は erlコマンド(shellスクリプト) から以下のように呼ばれますが、

```shell:/home/pojiro/.asdf/install/erlang/25.1/erts-13.1/bin/erl
#!/bin/sh
#
# %CopyrightBegin%
#
# Copyright Ericsson AB 1996-2022. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# %CopyrightEnd%
#
prog="$0"
progdir=`dirname "${prog}"`
dyn_erl_path="${progdir}/../erts-13.1/bin/dyn_erl"
if [ ! -f "$dyn_erl_path" ]
then
    dyn_erl_path="${progdir}/dyn_erl"
fi

if [ -f "$dyn_erl_path" ]
then
    dyn_rootdir=`"${dyn_erl_path}" --realpath`
    dyn_rootdir=`dirname "${dyn_rootdir}"`
    dyn_rootdir=`dirname "${dyn_rootdir}"`
    dyn_rootdir="${dyn_rootdir}"
else
    dyn_rootdir=""
fi

if [ -z "$ERL_ROOTDIR" ]
then
    ROOTDIR="/home/pojiro/.asdf/installs/erlang/25.1"
    if [ "$dyn_rootdir" != "$ROOTDIR" ] && [ "$dyn_rootdir" != "" ]
    then
        # It is likely that the files have been copied or moved
        ROOTDIR="$dyn_rootdir"
    fi
else
    ROOTDIR="$ERL_ROOTDIR"
fi
BINDIR="$ROOTDIR/erts-13.1/bin"
EMU=beam
PROGNAME=`basename "$0"`
export EMU
export ROOTDIR
export BINDIR
export PROGNAME
exec "$BINDIR/erlexec" ${1+"$@"}
```

Nerves では erlスクリプト は用いられず、 [erlinit](https://github.com/nerves-project/erlinit) が [nbtty](https://github.com/fhunleth/nbtty) 経由で `erlexec` を直接実行していました。
refs. https://github.com/nerves-project/erlinit/blob/v1.12.2/src/erlinit.c#L671-L806

`erlexec` はそれ自身で検索しても何なのか分かりませんでしたが、ドキュメント上 `erlexec` は [erl](https://www.erlang.org/doc/man/erl.html) としてそのオプション等が記述されていることが分かりました。また、ドキュメントを読むと、

>  The erl program starts an Erlang runtime system. The exact details (for example, whether erl is a script or a program and which other programs it calls) are system-dependent.

`erl` がスクリプトであるかプログラムであるかはシステム依存と記載がありました。このことから `erl` は `erlexec` のシステム依存で形式の異なるラッパーだろうと想像しています。

[erlinit](https://github.com/nerves-project/erlinit) のコードをざっとみたところとても興味が持てたので、時間を見てはerlinit を掘っていこうと思います🦾

erlinit や nbtty の理解には [Unix/Linuxプログラミング理論と実践](https://www.amazon.co.jp/dp/4048700219) が非常に役に立ちそうなので、冬休みはこれを読むことにします。