initプロセスはLinuxのシェルスクリプトにできますか?


14

私はそれが記載されているカスタムinitramfsのセットアップに関するチュートリアルを行っていました:

欠落しているのは/ initのみで、initramfsのルートにある実行可能ファイルは、カーネルがロードされるとカーネルによって実行されます。sys-apps / busyboxには完全に機能するシェルが含まれているため、/ initバイナリを単純なシェルスクリプトとして記述することができます(アセンブラーまたはCで記述された複雑なアプリケーションをコンパイルする必要はありません)。

で始まるシェルスクリプトとしてinitの例を示します #!/bin/busybox sh

これまでのところ、initは起動されるメインプロセスであり、他のすべてのユーザー空間プロセスは最終的にinitの子であるという印象を受けていました。ただし、指定された例では、最初のプロセスは、実際にbin/busybox/ shは後でinitが生成されます。

これは正しい解釈ですか?たとえば、その時点で使用可能なインタープリターがあれば、Pythonスクリプトなどとしてinitを書くことができますか?

回答:


12

initは(子プロセスとして)「生まれた」のではなく、されていないexec。このような「D:

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

execプロセス全体を適切に置き換えます。Initramfsのプロセスに先行していたとしても、最後のinitはまだ最初のプロセス(pid 1)です。

Initramfs /initは、pid 1のBusyboxシェルスクリプトであり、Busyboxにexecsですswitch_root(したがってswitch_rootpid 1になりました)。このプログラムはマウントポイントを変更するため/mnt/root、新しいものになり/ます。

switch_root再度execのよ/sbin/initあなたの本当のルートファイルシステムの。これにより、実際のinitシステムがpid 1を持つ最初のプロセスになり、任意の数の子プロセスが生成されます。

なんとかしてPythonをInitramfsに焼き付けることができれば、Pythonスクリプトでも同様に行うことができます。とにかくbusyboxを含める予定がない場合は、その機能の一部を苦労して再実装する必要があります(などswitch_root、通常は単純なコマンドで行うすべて)。

ただし、スクリプトバイナリ(CONFIG_BINFMT_SCRIPT=y)を許可しないカーネルでは機能しません。そのような場合は、インタープリターを直接起動して、何らかの方法でスクリプトをロードする必要があります。


/薄い空気の中に消えることはありません-それは上にマウントされます(通常、その内容はすべて、メモリを節約する前に削除されます)。それはまだそこにswitch_rootsyscallを実行します。switchrootこれは、カーネル2.6.somethingでブートプロセスを変更してinitramfsを必要とするときにカーネル開発者が提供したものです。魔法を行うのはカーネルです。
mikeserv 14

1
switchrootシステムコールは確かに私にニュースになります。そのためのソースはありますか?switch_root.cのソースコードを見ると、かなり手動のプロセスであるようで、Documentation / filesystems / ramfs-rootfs-initramfs.txtで説明されているものと同じです。また、すべてを削除してマウントすると、この時点でほとんど消えてしまいますよね?
frostschutz 14

pivot_root一方、syscallです。switch_rootしかし、それは使用されておらず、いくつかのフープを介してジャンプせずに使用することはできませんし、いずれにせよ、この答えには何の問題もないので、完全に削除しました。残念なことに、私は魔法と薄い空気への消失が本当にうまくいったと思った... :-P
frostschutz 14

まあ、多分私は間違った考えを得たswitch_root-申し訳ありませんが、私を見せてくれてありがとう-とにかく何も消えません。initramfsルートは永続的であり、常にすべてのユーザーに対して存在します。これルートです。
mikeserv 14

1
あなたがリンクしドキュメントのようにしかし、initramfsはrootfsです。pivot_rootrootfsもアンマウントもできません。代わりに、rootfsからすべてを削除してスペースを解放し(find -xdev / -exec rm '{}' ';')、rootfsを新しいルートでオーバーマウントし(cd /newmount; mount --move . /; chroot .)、stdin / stdout / stderrを新しい/ dev / consoleに接続し、新しいinitを実行します。
mikeserv 14

4

Linuxカーネルのex​​ec syscallはネイティブにシバンを理解します

実行されたファイルがmagic bytes #!で始まるとき、カーネルは次のように使用する#!/bin/shように指示します。

  • doとexecシステムコール
  • 実行可能 /bin/sh
  • およびCLI引数あり:現在のスクリプトへのパス

これは、通常のユーザーランドシェルスクリプトを次のコマンドで実行した場合とまったく同じです。

./myscript.sh

ファイルがの.ELF代わりにマジックバイトで始まっていた場合、#!カーネルは代わりにELFローダーを選択して実行します。

詳細:なぜ人々はPythonスクリプトの最初の行に#!/ usr / bin / env python shebangを書くのですか?| スタックオーバーフロー

これを念頭に置いておくと/init、シェルスクリプトなど、カーネルが実行できるものであれば何でも受け入れられ/bin/sh、その場合に最初の実行可能ファイルになる理由も受け入れやすくなります。

以下は、試してみたい人のための最小限の実行可能な例です:https : //github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.