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" であり、同様に便利です。
おそらくridinit=/bin/shを試してみてください
Linux カーネル ソースを見ると、ファイル /init が存在する場合、カーネルは、RAM ディスク ブートを行っていると想定して、常にそのファイルを実行しようとすることがわかります。システムに /init が存在するかどうかを確認してください。存在する場合は、おそらくそれが問題です。