initrd shenanigans
Wenn Sie initrd oder initramfs verwenden, beachten Sie Folgendes:
rdinit= wird anstelle von verwendet init=
wenn rdinit=nicht angegeben, sind die versuchten Standardpfade: /sbin/init, /etc/init, /bin/initund , /bin/shaber nicht/init
Wenn initrd nicht verwendet wird, /initwird der erste Pfad ausprobiert, gefolgt von den anderen.
v4.15 RTFS: Alles ist in der Datei https://github.com/torvalds/linux/blob/v4.15/init/main.c enthalten.
Zuerst lernen wir, dass:
execute_comand ist was auch immer übergeben wird an: init=
ramdisk_execute_command ist was auch immer übergeben wird an: rdinit=
wie man sieht aus:
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);
Wo __setupist ein magischer Weg, um Kommandozeilenparameter zu verarbeiten.
start_kernelruft der Kernel "Einstiegspunkt rest_init" kernel_initauf, der einen Thread "aufruft" :
pid = kernel_thread(kernel_init, NULL, CLONE_FS);
Dann kernel_initmacht:
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.");
}
und kernel_init_freeablemacht:
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: Verstehe sys_access.
Beachten Sie auch, dass es weitere Unterschiede zwischen RAM-Inits und Nicht-RAM-Inits gibt, z. B. beim Konsolen-Handling: Unterschied bei der Ausführung von init mit eingebetteten vs. externen Initramfs?
init? Möglicherweise ignorieren sie einfach die Befehlszeile. Vielleicht möchten Sie die initrd untersuchen und sehen, was die Skripte tatsächlich tun.