Minimal-Init-Hello-World-Programm Schritt für Schritt
Kompilieren Sie eine Hello World ohne Abhängigkeiten, die in einer Endlosschleife endet. init.S
:
.global _start
_start:
mov $1, %rax
mov $1, %rdi
mov $message, %rsi
mov $message_len, %rdx
syscall
jmp .
message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
.equ message_len, . - message
Wir können den Exit-Systemaufruf nicht verwenden, sonst gerät der Kernel in Panik. Die einzige Möglichkeit, die Initialisierung ordnungsgemäß zu beenden, besteht darin, die Maschine mit reboot
auszuschalten Systemaufruf.
Dann:
mkdir d
as --64 -o init.o init.S # assemble
ld -o d/init init.o # link
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"
Dies erstellt ein Dateisystem mit unserer Hallo Welt bei /init
, das das erste Userland-Programm ist, das der Kernel ausführen wird. Wir hätten auch mehr Dateien zu d/
hinzufügen können und sie wären über /init
zugänglich Programm, wenn der Kernel läuft.
Dann cd
in den Linux-Kernelbaum einfügen, wie gewohnt bauen und in QEMU ausführen:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"
Und Sie sollten eine Zeile sehen:
FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR
auf dem Emulator-Bildschirm! Beachten Sie, dass es nicht die letzte Zeile ist, also müssen Sie etwas weiter nach oben schauen.
Sie können auch C-Programme verwenden, wenn Sie sie statisch einbinden:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
sleep(0xFFFFFFFF);
return 0;
}
mit:
gcc -static init.c -o init
Dynamisches Linken würde das Einrichten einer ausführbaren dynamischen Linker-Datei erfordern, von denen die gebräuchlichsten Teil von C-Standardbibliotheken wie glibc sind.
Sie können auf echter Hardware mit einem USB auf /dev/sdX
laufen und:
make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX
Gute Quelle zu diesem Thema:Tech Tip:How to use initramfs | landley.net Es erklärt auch, wie man gen_initramfs_list.sh
verwendet , ein Skript aus dem Linux-Kernel-Quellbaum, um den Prozess zu automatisieren.
Getestet auf Ubuntu 16.10, QEMU 2.6.1.
Nächste Schritte
Als nächstes müssen Sie BusyBox einrichten.
BusyBox implementiert grundlegende POSIX-y-CLI-Dienstprogramme, einschließlich einer POSIX-y-Shell, mit der Sie einfacher interaktiv mit dem System experimentieren können.
Persönlich verlasse ich mich an dieser Stelle lieber auf Buildroot, eine erstaunliche Reihe von Skripten, die das Erstellen von allem aus der Quelle und das Erstellen des Root-Dateisystems automatisieren.
Ich habe dafür einen sehr detaillierten und automatisierten Helfer hochgeladen unter:https://github.com/cirosantilli/linux-kernel-module-cheat
Ich würde mich nicht mit LFS anlegen, das ist ein Gartenpfad, der zu dunklen Wäldern führt.
Beginnen Sie mit einer Distribution, bei der Sie viel Kontrolle über die Erstinstallation haben, z. B. Arch, oder eine Headless-Edition wie Ubuntu Server. Dabei geht es weniger um Platzersparnis als vielmehr um die Begrenzung der Komplexität der Init-Konfiguration; Ausgehend von einer Headless-Distribution, wenn die Anwendung, die Sie ausführen möchten, eine GUI erfordert, können Sie das hinzufügen, was dafür erforderlich ist, ohne mit einem GUI-Login (auch bekannt als Display Manager oder DM) enden zu müssen, das von init gestartet wird, und einem vollwertigen Desktop Umgebung dazu.
Anschließend möchten Sie lernen, wie Sie das Init-System für Ihre Zwecke konfigurieren -- beachten Sie, dass Sie ohne Init nicht auskommen können und es möglicherweise das beste Mittel ist, um Ihr Ziel zu erreichen. Das Init-System, das jetzt auf den meisten Linux-Distributionen verwendet wird, ist systemd.
Der Punkt hier ist, zu minimieren, was init beim Booten tut, und so können Sie ein System erstellen, das eine minimale Menge an Software ausführt, um die Anwendung zu unterstützen, auf die Sie sich konzentrieren möchten - so wird im Wesentlichen ein Server eingerichtet. Übrigens, es ist also eine häufige Aufgabe (beachten Sie, dass Sie nicht buchstäblich "nur einen" Userland-Prozess laufen lassen können, zumindest nicht sinnvoll).
Wenn die Anwendung, die Sie ausführen möchten, ein GUI-Programm ist (ein gutes Beispiel dafür, warum Sie nicht buchstäblich nur eine Anwendung ausführen können, da GUI-Anwendungen einen X-Server erfordern), können Sie einen ~/.xinitrc
haben das sieht so aus;
#!/bin/sh
myprogram
Wenn Sie dann startx
, wird Ihr Programm das einzige sein, was ausgeführt wird, und es wird unmöglich sein, Desktops zu ändern oder irgendetwas anderes zu starten, teilweise weil es keinen Fenstermanager oder keine Desktopumgebung gibt (daher gibt es auch keinen Fensterrahmen oder keine Titelleiste).
Wenn Sie ein wenig Programmiererfahrung haben und es von Grund auf neu erstellen möchten, können Sie LFS verwenden, d. h. Linux from Scratch http://www.linuxfromscratch.org/
Wenn Sie Ubutnu anpassen möchten, können Sie Ubunt-Builder verwenden, und wenn Sie es auf RPM-Basis möchten, können Sie SUsE-Studio verwenden. Mit Suse Studio können Sie benutzerdefiniertes Suse-Linux erstellen
Prost