manigances initrd
Si vous utilisez initrd ou initramfs, gardez à l'esprit ce qui suit :
-
rdinit=
est utilisé à la place deinit=
-
si
rdinit=
n'est pas donné, les chemins par défaut tentés sont :/sbin/init
,/etc/init
,/bin/init
et/bin/sh
mais pas/init
Lorsque vous n'utilisez pas initrd,
/init
est le premier chemin essayé, suivi des autres.
v4.15 RTFS :tout est contenu dans le fichier https://github.com/torvalds/linux/blob/v4.15/init/main.c.
Nous apprenons d'abord que :
execute_comand
est ce qui est passé à :init=
ramdisk_execute_command
est ce qui est passé à :rdinit=
comme on peut le voir sur :
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);
où __setup
est une manière magique de gérer les paramètres de la ligne de commande.
start_kernel
, le "point d'entrée" du noyau, appelle rest_init
, qui "appelle" kernel_init
sur un fil :
pid = kernel_thread(kernel_init, NULL, CLONE_FS);
Ensuite, kernel_init
fait :
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.");
}
et kernel_init_freeable
fait :
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();
}
À FAIRE :comprendre sys_access
.
Notez également qu'il existe d'autres différences entre les initialisations RAM et les initialisations non RAM, par ex. gestion de la console :Différence d'exécution d'init avec initramfs intégré et externe ?
Le
https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt
J'ai trouvé :
Lors du débogage d'un système de fichiers racine normal, il est agréable de pouvoir démarrer avec "init=/bin/sh". L'équivalent initramfs est "rdinit=/bin/sh", et c'est tout aussi utile.
Essayez donc probablement ridinit=/bin/sh
En regardant la source du noyau Linux, je vois que si le fichier /init existe, le noyau tentera toujours de l'exécuter en supposant qu'il effectue un démarrage sur disque virtuel. Vérifiez votre système pour voir si /init existe, si c'est le cas, alors c'est probablement votre problème.