GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Was kann dazu führen, dass das Übergeben von init=/path/to/program an den Kernel das Programm nicht als init startet?

initrd-Spielereien

Wenn Sie initrd oder initramfs verwenden, beachten Sie Folgendes:

  • rdinit= wird anstelle von init= verwendet

  • wenn rdinit= nicht angegeben ist, sind die versuchten Standardpfade:/sbin/init , /etc/init , /bin/init und /bin/sh aber nicht /init

    Wenn initrd nicht verwendet wird, /init ist der erste Pfad, der versucht wird, 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 das:

  • execute_comand ist, was übergeben wird:init=
  • ramdisk_execute_command ist, was übergeben wird:rdinit=

wie ersichtlich 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);

wobei __setup ist eine magische Art, Befehlszeilenparameter zu handhaben.

start_kernel , der "Einstiegspunkt" des Kernels, ruft rest_init auf , die kernel_init "aufruft". in einem Thread:

pid = kernel_thread(kernel_init, NULL, CLONE_FS);

Dann kernel_init tut:

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_freeable tut:

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. Konsolenhandhabung:Unterschied in der Ausführung von init mit eingebettetem vs. externem initramfs?


Auf

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

Ich habe gefunden:

Beim Debuggen eines normalen Root-Dateisystems ist es schön, mit "init=/bin/sh" booten zu können. Das initramfs-Äquivalent ist "rdinit=/bin/sh", und es ist genauso nützlich.

Versuchen Sie also wahrscheinlich ridinit=/bin/sh


Wenn ich mir die Linux-Kernel-Quelle ansehe, sehe ich, dass der Kernel, wenn die Datei /init existiert, immer versucht, sie unter der Annahme auszuführen, dass er einen Ramdisk-Boot durchführt. Überprüfen Sie Ihr System, um zu sehen, ob /init existiert, wenn ja, dann ist das wahrscheinlich Ihr Problem.


Linux
  1. Was genau macht make oldconfig im Makefile des Linux-Kernels?

  2. Was ist die aktuelle Linux-Kernelquelle?

  3. Wie kann ich mit dem Fenstermanager ein Programm als root starten?

  4. Wie kann ich den absoluten Pfad eines laufenden Prozesses erfahren?

  5. Was ist die maximale Anzahl von IPs, die einem bestimmten Computer zugewiesen werden können?

Wie lautet der Pfad zu meinem Root-Home-Verzeichnis, wie kann er geändert werden?

Absoluter vs. relativer Pfad in Linux:Was ist der Unterschied?

Was kann dazu führen, dass SIGHUP erzeugt wird?

Lassen Sie den Computer aus der Ferne über den eingebauten Lautsprecher piepen

Übergeben von Optionen an ein Programm:Was ist die Konvention für einen Bindestrich im Vergleich zu zwei?

libvirt:Wie kann ich eine Domain starten lassen, wenn der Host startet?