GNU/Linux >> Linux の 問題 >  >> Linux

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

initrd の悪ふざけ

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 、カーネルの「エントリポイント」で、rest_init を呼び出します kernel_init を「呼び出す」 スレッド:

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 init と非 ram init の間にはさらに違いがあることにも注意してください。コンソールの処理:組み込みの init と外部の initramfs を使用した init の実行の違いは?


オン

https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt

見つけました:

<ブロック引用>

通常のルート ファイルシステムをデバッグする場合、"init=/bin/sh" で起動できると便利です。 initramfs に相当するものは "rdinit=/bin/sh" であり、同様に便利です。

おそらくri​​dinit=/bin/shを試してみてください


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


Linux
  1. Linux カーネルの makefile で make oldconfig が正確に行うことは何ですか?

  2. 現在の Linux カーネル ソースは何ですか?

  3. ウィンドウマネージャを使用してルートとしてプログラムを起動するにはどうすればよいですか?

  1. シェルを使用してinitシステムを検出しますか?

  2. PATH を変更しました。すべてのコマンドが見つかりませんでした

  3. シグナル 11 の原因は何ですか?

  1. Linux –デーモンをLinuxで起動させますか?

  2. Linux –カーネルがInitを実行できないのはなぜですか?

  3. Linuxでpythonプログラムを実行可能にするために何を使用しますか