私は カスタムinitramfsの設定に関するチュートリアル を実行していました:
不足しているのは/ initだけです。これは、ロードされるとカーネルによって実行されるinitramfsのルートにある実行可能ファイルです。 sys-apps/busyboxには完全に機能するシェルが含まれているため、/ initバイナリを単純なシェルスクリプトとして記述できます(アセンブラーまたはCでコンパイルする必要のある複雑なアプリケーションにする必要はありません)。
#!/bin/busybox sh
で始まるシェルスクリプトとしてのinitの例を示します
これまでのところ、私はinitが起動されるメインプロセスであり、他のすべてのユーザー空間プロセスは最終的にinitの子であるという印象を受けました。ただし、この例では、最初のプロセスは実際にはbin/busybox/ sh
であり、そこから後でinitが生成されます。
これは正しい解釈ですか?たとえば、その時点で利用可能なインタープリターがあった場合、Pythonスクリプトなどとしてinitを書くことができますか?
initは(子プロセスとして)「生成」されるのではなく、exec
は次のようになります。
# Boot the real thing.
exec switch_root /mnt/root /sbin/init
exec
は所定のプロセス全体を置き換えます。 Initramfsのプロセスが先行していたとしても、最後のinitはまだ最初のプロセス(pid 1)です。
Initramfs /init
、これはpid 1、exec
sをBusybox switch_root
に変換したBusyboxシェルスクリプトです(したがって、switch_root
はpid 1)。このプログラムは、/mnt/root
が新しい/
になるようにマウントポイントを変更します。
switch_root
次に、実際のルートファイルシステムのexec
sから/sbin/init
へ。これにより、実際のinitシステムがpid 1の最初のプロセスになり、任意の数の子プロセスが生成されます。
確かに、Pythonスクリプトを使用して、PythonをInitramfsに焼き付けた場合、とにかくbusyboxを含めると、その機能の一部(switch_root
など、通常は単純なコマンドで実行するすべてのこと)を入念に再実装する必要があります。
ただし、スクリプトバイナリ(CONFIG_BINFMT_SCRIPT=y
)を許可しないカーネルでは機能しません。そのような場合は、インタープリターを直接起動して、なんらかの方法でスクリプトをロードする必要があります。
Linuxカーネルのexec syscallはネイティブでシバンを過小評価します
実行されたファイルがマジックバイト#!
で始まる場合、カーネルは#!/bin/sh
を次のように使用するように指示します。
exec
システムコール/bin/sh
これは、通常のユーザーランドシェルスクリプトを次のように実行した場合とまったく同じです。
./myscript.sh
ファイルが.ELF
ではなくマジックバイト#!
で始まっていた場合、カーネルは代わりにELFローダーを選択して実行します。
詳細: なぜ人々は#!/ usr/bin/env python ShebangをPythonスクリプトの最初の行に書くのですか? |スタックオーバーフロー
これを頭に入れておくと、/init
は、シェルスクリプトを含め、カーネルが実行できるすべてのものであり、/bin/sh
がその場合の最初の実行可能ファイルになる理由を簡単に受け入れることができます。
試してみたい人のための最小限の実行可能な例を次に示します。 https://github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init