Wie sich Computer aus dem Datensumpf ziehen

Wie sich Computer aus dem Datensumpf ziehen

Das Wort “bootstrapping” lehnt sich an eine Geschichte des SF-Autors Heinlein an, der die Idee wohl vom Lügenbaron Münchhausen übernahm, der vorgab sich mit seinen Stiefelriemen einmal aus einem Sumpf gezogen zu haben.

Für alle modernen Computer ist der Systemstart ein kompliziertes und leider auch langwieriges Verfahren, so mancher neue Fernseher braucht länger zum Einschalten als ein altes Röhrengerät zum Aufheizen der Röhren. Selbst der für das Betriebssystem verwendete Prozessor ist nicht sofort verfügbar, zuerst hat eine Management Engine (ME) im Prozessorchip Aufgaben wie die Herstellung aller Verbindungen zum Hauptprozessor und nicht nur bei Complex-Instruction-Set (CISC)- Computern wird der für komplexere Prozessor-Instruktionen notwendige Microcode erst mal geladen. Die benötigte Menge an nicht veränderbarem Read-Only-Memory (ROM) wird minimiert, um Prozessorbugs noch mittels aus programmierbarem Flash-Speicher geladenem Code korrigieren zu können. Dieser Flash-Speicher wurde früher BIOS genannt, heute hat sich mit Unified Extensible Firmware (UEFI) ein viel komplexeres Stück Software durchgesetzt. In den Core Prozessoren von Intel ist schon die im Prozessorchip integrierte ME ein Clone des unixoiden Betriebssystems Minix und das den ganzen Bootvorgang von außen steuernde UEFI ist noch weitaus komplexer.

Kein Windows ohne Minix

Auch Windows läuft also ohne den Unix-Clone Minix nicht, weil es den Computer selbst gar nicht zum Laufen bringen kann. Auch populäre Microcontroller wie der ESP8266 haben nur genug ROM, um sich aus einem externem Flash-Speicher eine Konfiguration und Programmcode in den Arbeitsspeicher zu laden, während der eigentliche Prozessor noch ruht.

Nachdem die erste Bootphase den Prozessorchip und essentielle “Peripherie”, vor allem auch benötigte Arbeitsspeicher- Bereiche vorbereitet hat, kann der Prozessor resettet werden, um einen Urlader - etwa U-Boot genannt - von externem Speicher zu laden - etwa von einem “Bootsektor” oder anderem festgelegten Bereich des Massenspeichers. Bei Desktop-Linux heißen diese Betriebssystem-Lader Grub oder Lilo und müssen noch im uralten 80286-Modus des modernen Intel-Prozessors laufen , beim Raspberry gibt es für den Start eine Datei "bootcode.bin"in der Boot-Partition. Beim Raspberry Pi 4 ersetzt aber ein programmierbares EEPROM diese externe Datei, deren Zweck nur das Laden einer Datei start.elf ist.

Raspi auch nicht (mehr) ganz einfach

Da der Bootvorgang eines Raspberry Pi noch einigermaßen überschaubar abläuft, beschränke ich mich hier nun auf diesen in verkürzter Form, im Detail wird er hier beschrieben. Neuere Raspis können sowohl von einer SD-Speicherkarte als auch einem USB-Gerät booten, auf dem eine FAT-Partition (altes MSDOS Diskettenformat) zu finden ist, die später als /boot Verzeichnis gemounted wird. Diese Partition enthält die oben erwähnte start.elf, zwei Textdateien config.txt und cmdline.txt, mehrere Kernel-Images und diverse DTB (device tree blob) Dateien. Letztere enthalten unterschiedliche Device Trees, die wegen der unterschiedlich ausgestatteten Raspberry-Versionen gebraucht werden. Eine vollständige Beschreibung des Inhalts der Boot-Partition befindet sich hier.

Die Datei config.txt wird verwendet, um die in Varianten vorliegende Elf-Datei auszuwählen, die wiederum mit Hilfe der Device-Trees eine passende Geräte & Treiber-Konfiguration für einen Raspi festlegt. In dieser Phase wird vor allem weitere Firmware und Konfiguration in weitere Komponenten geladen, damit der Raspi sie ansprechen kann.

Erst wenn die gesamte Hardware richtig konfiguriert ist, kommt der konfigurierte Linux-Kernel ins Spiel, dem die Befehlszeile in cmdline.txt beim Start übergeben wird, wobei noch die root-Partition und eine Konsolen-Schnittstelle mitgeteilt werden muß:

console=serial0,115200 console=tty1 root=PARTUUID=92b764b9-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

Die root-Partition wird über eine PARTUUID identifiziert, die beim Formattieren vergeben wird. Hier kann sich durch Neuformattierung oder “Klonen” von Speicherkarten leicht das Problem ergeben, dass der Kernel keine Root-Partition mehr findet.

Unix V Init vs. Systemd

Nun erst ist das System per Konsole mit der “Außenwelt” verbunden und kann den Bootvorgang des eigentlichen Betriebssystems Linux loggen. Der Log wird aber auch abgespeichert und kann mit dem Befehl dmesg verfolgt werden. Auch spätere Systemveränderungen wie “Hotplugging” von USB-Geräten werden hier gelogged, sodaß man dmesg oft nutzt, wenn ein Gerät sich nicht verbindet bzw. unter welcher Device-Addresse es im Erfolgsfall zu finden ist.

Nach dem Start wird bei einigen (vor allem älteren) Linux Distributionen noch der Startprozess /sbin/init gestartet, der in verschiedenen runlevels weitere Service-Programme startet, etwa auch getty für jedes verbundene Terminal, damit Benutzer dort einloggen können, sshd für SSH Anmeldungen über das Netzwerk, oder Fenstermanager wie den xdm für graphische Desktops.

Bei den meisten Linux-Distributionen ist diese ursprünglich von Unix System V stammende Prozess-Management aber durch einen Systemd genannten Service ersetzt worden, so auch bei Debian Linux, der Grundlage für Raspberry OS.

Für Systemd werden in /etc/systemd/system Service-Definitions-Dateien angelegt, worauf diese Services mit dem Kommando systemctl gestartet und gestoppt werden können bzw. beim Booten automatisch gestartet werden.

Für den erwähnten sshd-Service etwa gibt es die Datei /etc/systemd/system/sshd.service:

[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
Alias=sshd.service

Für höheren Konfigurationsaufwand mit mehreren Dateien können Services auch Unterverzeichnisse unter /etc/systemd/system anlegen, etwa finden sich unter bluetooth.target.wants Bluetooth-Geräte und die Gettys für die Terminals stehen im Unterverzeichnis getty.target.wants:

#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

# IgnoreOnIsolate causes issues with sulogin, if someone isolates
# rescue.target or starts rescue.service from multi-user.target or
# graphical.target.
Conflicts=rescue.service
Before=rescue.service

# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by serial-getty@.service, not this
# unit.
ConditionPathExists=/dev/tty0

[Service]
# the VT is cleared by TTYVTDisallocate
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION

[Install]
WantedBy=getty.target
DefaultInstance=tty1

Fazit

Es ist schon erstaunlich, was für ein komplexes und vielseitiges System auch schon ein Raspberry Zero für 20€ darstellt, der mit einem Debian letztlich das gleiche Debian Betriebssystem verwendet, das auch manchen Supercomputer oder Megaserver betreibt. Da zeigt sich der Unterschied zu Windows, was nur auf PC-Desktops zufriedenstellend (?) läuft und faktisch nicht skalierbar ist - wie viele von Microsoft’s Fehlversuchen mit Mobilgeräten, Servern und Embedded-Systemen aufzeigen.

Der von mir zusammengestellte kleine Node-Red Server kann durchaus auch noch sinnvoll auf einem Raspberry Zero betrieben zum Herzstück einer simplen Heimautomation werden. Die Offenheit bzw. Konfigurierbarkeit von Debian und anderen Linux - Distributionen erlaubt eine Vielfalt, die mit proprietärer Software niemals erreichbar sein kann.

War dieser Artikel hilfreich? Bewertungen: 0
Artikeldetails:
Veröffentlichungsdatum: 2020-12-31 10:42AM
Zuletzt aktualisiert: 2020-12-31 3:04PM (Klaus - klaus@zerbe.cloud)
Artikel teilen: 
Autor: Klaus (klaus@zerbe.cloud)
Permalink: http://openkb.zerbe.cloud/kb/wie-sich-computer-aus-dem-datensumpf-ziehen