init = / path / to / programをカーネルに渡すと、プログラムがinitとして起動しないのはなぜですか?


13

Linuxシステムでinitスクリプトをデバッグしようとしています。initシーケンスを手動で実行できるようにinit=/bin/sh、カーネルに渡して起動shせずに起動しようとしていますinit

私が見つけたのは、initとにかくカーネルが起動しているということです。起動中、printkメッセージの1つはコマンドラインであり、それはラインが適切に設定されていることを示しています。さらに、カーネルコマンドラインを使用して他のことに影響を与えることができます。パスが存在することを確認しました。します。

これはbusyboxシステムであり、initはbusyboxへのシンボリックリンクです。そのため、PIDが1の場合にbusyboxが奇妙な魔法を起こさないようにするために、busybox以外のプログラムをinitとして実行してみました。それもうまくいきませんでした。何をしても、initが実行されるようです。

この動作の原因は何ですか?


busyboxを使用しているベースディストリビューションは何initですか?彼らは単にコマンドラインを無視しているだけかもしれません...あなたはinitrd調べて、スクリプトが実際に何をしているかを見たいかもしれません。
アーロンD.マラスコ

それはディストリビューションではありません-私自身のビルドです; これが、initスクリプトをデバッグしようとしている理由です。
ショーンJ.ゴフ

回答:


3

Linuxカーネルソースを見ると、/ initファイルが存在する場合、カーネルは常にRAMディスクブートを実行しているという前提で実行しようとすることがわかります。システムをチェックして/ initが存在するかどうかを確認し、存在する場合は、おそらくそれが問題です。


実際には、execute_command最初に確認しinit=ます。これは、カーネルコマンドラインパラメーターから取得されます。実行できない場合、警告を出力し、initさまざまな場所で実行を試みます。これはinit/main.c関数にありますinit_post()。カーネルのprintkメッセージを調べて、カーネルの出力で警告を見つけたので、/ bin / shまたは起動しようとする他の何かを起動できない理由を理解する必要があります。
ショーンJ.ゴフ

私が見たコード(v3.2.2と思います)は、set ramdisk_execute_commandが設定されていない場合にチェックし、実行しようとしたため、その最新のものであってはなりません。残念です、それを説明するものが他になかったからです。
カイルジョーンズ

rdinit明らかにramdiskから起動するときに使用する必要があります:unix.stackexchange.com/a/430614/32558
Ciro Santilli新疆改造中心法轮功六四事件

8

initrd shenanigans

initrdまたはinitramfsを使用している場合、次のことに注意してください。

  • rdinit= の代わりに使用されます init=

  • 場合はrdinit=与えられていない、試みたデフォルトのパスは次のとおり/sbin/init/etc/init/bin/init/bin/shではなく、/init

    initrdを使用しない場合/init、最初のパスが試行され、他のパスがそれに続きます。

v4.15 RTFS:すべてがhttps://github.com/torvalds/linux/blob/v4.15/init/main.cファイル内に含まれています。

まず、次のことを学びます。

  • execute_comand に渡されるものは何でも: init=
  • ramdisk_execute_command に渡されるものは何でも: rdinit=

以下からわかるように:

static int __init init_setup(char *str)
{
    unsigned int i;

    execute_command = str;
    /*
    * In case LILO is going to boot us with default command line,
    * it prepends "auto" before the whole cmdline which makes
    * the shell think it should execute a script with such name.
    * So we ignore all arguments entered _before_ init=... [MJ]
    */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("init=", init_setup);

static int __init rdinit_setup(char *str)
{
    unsigned int i;

    ramdisk_execute_command = str;
    /* See "auto" comment in init_setup */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("rdinit=", rdinit_setup);

どこ__setupがコマンドラインパラメータを処理する魔法の方法です。

start_kernel、カーネルの「エントリポイント」、calls rest_initkernel_initスレッドで「calls」:

pid = kernel_thread(kernel_init, NULL, CLONE_FS);

それからkernel_init

static int __ref kernel_init(void *unused)
{
    int ret;

    kernel_init_freeable();

    [...]

    if (ramdisk_execute_command) {
        ret = run_init_process(ramdisk_execute_command);
        if (!ret)
            return 0;
        pr_err("Failed to execute %s (error %d)\n",
            ramdisk_execute_command, ret);
    }

    [...]

    if (execute_command) {
        ret = run_init_process(execute_command);
        if (!ret)
            return 0;
        panic("Requested init %s failed (error %d).",
            execute_command, ret);
    }
    if (!try_to_run_init_process("/sbin/init") ||
        !try_to_run_init_process("/etc/init") ||
        !try_to_run_init_process("/bin/init") ||
        !try_to_run_init_process("/bin/sh"))
        return 0;

    panic("No working init found.  Try passing init= option to kernel. "
        "See Linux Documentation/admin-guide/init.rst for guidance.");
}

そしてkernel_init_freeable

static noinline void __init kernel_init_freeable(void)
{

    [...]

    if (!ramdisk_execute_command)
        ramdisk_execute_command = "/init";

    if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
        ramdisk_execute_command = NULL;
        prepare_namespace();
    }

TODO:理解するsys_access

また、RAMの初期化と非RAMの初期化の間には、コンソールの処理など、さらに違いがあることに注意してください



0

Linuxカーネルをカスタマイズして再コンパイルできます。4.9カーネルの場合、init / main.cの関数「kernel_init」を編集し、最初に次の行を実行してみてください。

try_to_run_init_process("/bin/sh")

また、BootLoaderから渡されたカーネルパラメーターが原因である可能性があります。

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