Das hängt ganz davon ab, welche Dienste Sie auf Ihrem Gerät haben möchten.
Programme
Sie können Linux direkt in eine Shell booten lassen . Es ist in der Produktion nicht sehr nützlich – wer möchte nur eine Shell haben – aber es ist nützlich als Interventionsmechanismus, wenn Sie einen interaktiven Bootloader haben:Übergeben Sie init=/bin/sh
zur Kernel-Befehlszeile. Alle Linux-Systeme (und alle Unix-Systeme) haben eine Shell im Bourne/POSIX-Stil in /bin/sh
.
Sie benötigen eine Reihe von Shell-Dienstprogrammen . BusyBox ist eine sehr häufige Wahl; Es enthält eine Shell und allgemeine Dienstprogramme für die Datei- und Textbearbeitung (cp
, grep
, …), Netzwerkeinrichtung (ping
, ifconfig
, …), Prozessmanipulation (ps
, nice
, …) und verschiedene andere Systemtools (fdisk
, mount
, syslogd
, …). BusyBox ist extrem konfigurierbar:Sie können während der Kompilierung die gewünschten Tools und sogar einzelne Funktionen auswählen, um den richtigen Kompromiss aus Größe und Funktionalität für Ihre Anwendung zu finden. Abgesehen von sh
, das absolute Minimum, ohne das Sie wirklich nichts tun können, ist mount
, umount
und halt
, aber es wäre untypisch, nicht auch cat
zu haben , cp
, mv
, rm
, mkdir
, rmdir
, ps
, sync
und noch ein paar mehr. BusyBox wird als einzelne Binärdatei mit dem Namen busybox
installiert , mit einem symbolischen Link für jedes Dienstprogramm.
Der erste Prozess auf einem normalen Unix-System heißt init
. Seine Aufgabe ist es, andere Dienste zu starten. BusyBox enthält ein Init-System. Zusätzlich zum init
binär (normalerweise in /sbin
), benötigen Sie seine Konfigurationsdateien (normalerweise /etc/inittab
— Einige moderne Init-Ersetzungen beseitigen diese Datei, aber Sie werden sie nicht auf einem kleinen eingebetteten System finden), die angeben, welche Dienste wann gestartet werden sollen. Für BusyBox, /etc/inittab
es ist optional; wenn es fehlt, bekommt man eine Root-Shell auf der Konsole und das Skript /etc/init.d/rcS
(Standardspeicherort) wird beim Booten ausgeführt.
Das ist alles, was Sie brauchen, abgesehen von den Programmen, die Ihr Gerät dazu bringen, etwas Nützliches zu tun. Beispielsweise sind auf meinem Heimrouter, auf dem eine OpenWrt-Variante ausgeführt wird, die einzigen Programme BusyBox, nvram
(zum Lesen und Ändern von Einstellungen im NVRAM) und Netzwerkdienstprogramme.
Sofern nicht alle Ihre ausführbaren Dateien statisch gelinkt sind, benötigen Sie den dynamischen Loader (ld.so
, die je nach Wahl der libc und der Prozessorarchitektur unter verschiedenen Namen aufgerufen werden können) und alle dynamischen Bibliotheken (/lib/lib*.so
, vielleicht einige davon in /usr/lib
), die von diesen ausführbaren Dateien benötigt werden.
Verzeichnisstruktur
Der Filesystem Hierarchy Standard beschreibt die gemeinsame Verzeichnisstruktur von Linux-Systemen. Es ist auf Desktop- und Serverinstallationen ausgerichtet:Vieles davon kann auf einem eingebetteten System weggelassen werden. Hier ist ein typisches Minimum.
/bin
:ausführbare Programme (einige befinden sich möglicherweise in/usr/bin
stattdessen)./dev
:Geräteknoten (siehe unten)/etc
:Konfigurationsdateien/lib
:gemeinsam genutzte Bibliotheken, einschließlich des dynamischen Ladeprogramms (es sei denn, alle ausführbaren Dateien sind statisch gelinkt)/proc
:Einhängepunkt für das proc-Dateisystem/sbin
:ausführbare Programme. Die Unterscheidung mit/bin
ist das/sbin
ist für Programme, die nur für den Systemadministrator nützlich sind, aber diese Unterscheidung ist auf eingebetteten Geräten nicht sinnvoll. Sie können/sbin
machen ein symbolischer Link zu/bin
./mnt
:Praktisch für schreibgeschützte Root-Dateisysteme als Scratch-Mount-Punkt während der Wartung/sys
:Einhängepunkt für das sysfs-Dateisystem/tmp
:Speicherort für temporäre Dateien (häufig eintmpfs
montieren)/usr
:enthält Unterverzeichnissebin
,lib
undsbin
./usr
existiert für zusätzliche Dateien, die sich nicht im Root-Dateisystem befinden. Wenn Sie das nicht haben, können Sie/usr
machen ein symbolischer Link zum Root-Verzeichnis.
Gerätedateien
Hier sind einige typische Einträge in einem minimalen /dev
:
console
full
(Schreiben darauf meldet immer „no space left on device“)log
(ein Socket, den Programme zum Senden von Protokolleinträgen verwenden), wenn Sie einensyslogd
haben Daemon (wie BusyBox's) davon liestnull
(verhält sich wie eine Datei, die immer leer ist)ptmx
und einpts
Verzeichnis, wenn Sie Pseudo-Terminals verwenden möchten (d. h. jedes andere Terminal als die Konsole) – z. wenn das Gerät vernetzt ist und Sie sich per Telnet oder SSH anmelden möchtenrandom
(gibt zufällige Bytes zurück, riskiert Blockierung)tty
(bezeichnet immer das Terminal des Programms)urandom
(gibt zufällige Bytes zurück, blockiert nie, kann aber auf einem frisch gebooteten Gerät nicht zufällig sein)zero
(enthält eine unendliche Folge von Null-Bytes)
Darüber hinaus benötigen Sie Einträge für Ihre Hardware (außer Netzwerkschnittstellen, diese erhalten keine Einträge in /dev
):serielle Schnittstellen, Speicher usw.
Für eingebettete Geräte würden Sie die Geräteeinträge normalerweise direkt im Root-Dateisystem erstellen. High-End-Systeme haben ein Skript namens MAKEDEV
um /dev
zu erstellen Einträge, aber auf einem eingebetteten System wird das Skript oft nicht in das Bild gebündelt. Wenn einige Hardware Hotplugs sein kann (z. B. wenn das Gerät einen USB-Host-Anschluss hat), dann /dev
sollte von udev verwaltet werden (Möglicherweise haben Sie noch eine minimale Menge im Root-Dateisystem).
Aktionen beim Booten
Neben dem Root-Dateisystem müssen Sie für den normalen Betrieb noch ein paar weitere einhängen:
- procfs auf
/proc
(eigentlich unverzichtbar) - sysfs auf
/sys
(eigentlich unverzichtbar) tmpfs
Dateisystem auf/tmp
(um Programmen zu ermöglichen, temporäre Dateien zu erstellen, die sich im RAM befinden, anstatt im Root-Dateisystem, das sich möglicherweise im Flash- oder schreibgeschützten Format befindet)- tmpfs, devfs oder devtmpfs auf
/dev
falls dynamisch (siehe udev in „Gerätedateien“ oben) - devpts auf
/dev/pts
wenn Sie [Pseudo-Terminals verwenden wollen (siehe Anmerkung zupts
oben)
Sie können einen /etc/fstab
machen Datei und rufen Sie mount -a
auf , oder führen Sie mount
aus manuell.
Starten Sie einen Syslog-Daemon (sowie klogd
für Kernel-Logs, wenn der syslogd
Programm kümmert sich nicht darum), wenn Sie einen Ort haben, an den Sie Protokolle schreiben können.
Danach ist das Gerät bereit, anwendungsspezifische Dienste zu starten.
Wie man ein Root-Dateisystem erstellt
Dies ist eine lange und vielfältige Geschichte, daher gebe ich hier nur ein paar Hinweise.
Das Root-Dateisystem kann im RAM (geladen von einem (normalerweise komprimierten) Image im ROM oder Flash) oder auf einem festplattenbasierten Dateisystem (gespeichert im ROM oder Flash) gespeichert oder ggf. aus dem Netzwerk (oft über TFTP) geladen werden . Wenn sich das Root-Dateisystem im RAM befindet, machen Sie es zum initramfs – einem RAM-Dateisystem, dessen Inhalt beim Booten erstellt wird.
Es gibt viele Frameworks zum Zusammenstellen von Root-Images für eingebettete Systeme. Es gibt ein paar Hinweise in der BusyBox FAQ. Buildroot ist ein beliebtes Tool, mit dem Sie ein vollständiges Root-Image mit einem Setup erstellen können, das dem Linux-Kernel und der BusyBox ähnelt. OpenEmbedded ist ein weiteres solches Framework.
Wikipedia hat eine (unvollständige) Liste beliebter Embedded-Linux-Distributionen. Ein Beispiel für eingebettetes Linux, das Sie möglicherweise in Ihrer Nähe haben, ist die OpenWrt-Familie von Betriebssystemen für Netzwerkgeräte (beliebt bei Heimroutern von Tüftlern). Wenn Sie durch Erfahrung lernen möchten, können Sie Linux von Grund auf ausprobieren, aber es ist eher auf Desktop-Systeme für Bastler als auf eingebettete Geräte ausgerichtet.
Ein Hinweis zu Linux vs. Linux-Kernel
Das einzige Verhalten, das in den Linux-Kernel eingebrannt ist, ist, dass das erste Programm beim Booten gestartet wird. (Ich werde hier nicht auf die Feinheiten von initrd und initramfs eingehen.) Dieses Programm, traditionell init genannt, hat die Prozess-ID 1 und hat bestimmte Privilegien (Immunität gegen KILL-Signale) und Verantwortlichkeiten (das Ernten von Waisen). Sie können ein System mit einem Linux-Kernel ausführen und als ersten Prozess starten, was immer Sie wollen, aber dann haben Sie ein Betriebssystem, das auf dem Linux-Kernel basiert, und nicht das, was normalerweise „Linux“ genannt wird – Linux im allgemeinen Sinne des Begriffs, ist ein Unix-ähnliches Betriebssystem, dessen Kernel der Linux-Kernel ist. Beispielsweise ist Android ein Betriebssystem, das nicht Unix-ähnlich ist, sondern auf dem Linux-Kernel basiert.
Alles, was Sie brauchen, ist eine statisch verknüpfte ausführbare Datei, die isoliert auf dem Dateisystem abgelegt wird. Sie benötigen keine weiteren Dateien. Diese ausführbare Datei ist der Init-Prozess. Es kann Busybox sein. Das gibt Ihnen eine Shell und eine Menge anderer Dienstprogramme, alles in sich. Sie können zu einem voll funktionsfähigen System wechseln, indem Sie einfach Befehle manuell in busybox ausführen, um das Root-Dateisystem mit Lese- und Schreibzugriff einzuhängen, /dev-Knoten zu erstellen, reale Init auszuführen usw.
Wenn Sie keine Shell-Utilities benötigen, ist ein statisch gelinkter mksh
binär (z. B. gegen klibc – 130K auf Linux/i386) reicht aus. Sie benötigen einen /linuxrc
oder /init
oder /sbin/init
Skript, das einfach mksh -l -T!/dev/tty1
aufruft in einer Schleife:
#!/bin/mksh
while true; do
/bin/mksh -l -T!/dev/tty1
done
Die -T!$tty
Option ist eine neue Ergänzung zu mksh
Das weist es an, eine neue Shell auf dem angegebenen Terminal zu erzeugen und darauf zu warten. (Davor gab es nur -T-
um ein Programm zu dæmonisieren und -T$tty
auf einem Terminal spawnen, aber nicht darauf warten. Das war nicht so schön.) Der -l
Option weist es einfach an, eine Login-Shell auszuführen (die /etc/profile
liest , ~/.profile
und ~/.mkshrc
).
Dies setzt voraus, dass Ihr Terminal /dev/tty1
ist , Ersatz. (Mit mehr Magie kann das Terminal automatisch gefunden werden. /dev/console
gibt Ihnen keine vollständige Jobkontrolle.)
Sie benötigen einige Dateien in /dev
damit das funktioniert:
- /dev/console
- /dev/null
- /dev/tty
- /dev/tty1
Booten mit der Kernel-Option devtmpfs.mount=1
macht ein gefülltes /dev
überflüssig , lassen Sie es einfach ein leeres Verzeichnis sein (geeignet für die Verwendung als Einhängepunkt).
Normalerweise möchten Sie einige Dienstprogramme haben (von klibc, busybox, beastiebox, toybox oder toolbox), aber sie werden nicht wirklich benötigt.
Vielleicht möchten Sie einen ~/.mkshrc
hinzufügen Datei, die $PS1 und einige grundlegende Shell-Aliasnamen und -Funktionen einrichtet.
Ich habe einmal eine 171 KB komprimierte (371 KB unkomprimierte) initrd für Linux/m68k erstellt, wobei ich nur mksh (und seine mkshrc-Beispieldatei) und klibc-utils verwendet habe. (Dies war jedoch, bevor -T! zur Shell hinzugefügt wurde, sodass die Login-Shell auf /dev/tty2
erzeugt wurde stattdessen und gab eine Nachricht an die Konsole zurück, die den Benutzer aufforderte, die Terminals zu wechseln.) Es funktioniert gut.
Dies ist ein wirklich absolutes Minimum Konfiguration. Die anderen Antworten bieten ausgezeichnete Ratschläge für etwas umfangreichere Systeme. Das ist ein echter Sonderfall.
Haftungsausschluss:Ich bin der mksh-Entwickler.