- Mikro-kernel, die früher wegen ihres hohen Overheads wenig praxistauglich waren, könnten dank heute weit verbreiteter IOMMUs und Shared Memory wieder eine realistische Option sein
- Wenn Treiber und Subsysteme in den Userspace isoliert werden, lässt sich der Wirkungsbereich von Fehlern oder Angriffen begrenzen, was Sicherheit, Zuverlässigkeit und Modularität erhöht
- In den 1980er- und 1990er-Jahren konnten Userspace-Prozesse nicht direkt auf Geräte zugreifen, sodass Vorgänge wie ein Disk-Read jedes Mal System Calls und Kontextwechsel, Locks und Speicherkopien nach sich zogen
- Mit IOMMU und gemeinsamen Command Queues lassen sich auf dem Normalpfad asynchrone IPC und Gerätezugriffe ohne Kontextwechsel, Kopien zwischen Adressräumen und Locks abwickeln
- Bestehende Komponenten wie Xen, FreeBSD und Linux DRM können genutzt werden, sodass auch der Aufwand, Hypervisor und System-Server von Grund auf neu zu bauen, nicht allzu groß ist
Aufbau von Mikro-kerneln und Wirkung der Isolation
- Ein Mikro-kernel ist eine Kernel-Architektur, bei der Funktionen mit Ausnahme von Scheduling, Verwaltung des Zugriffs auf I/O-Geräte und Interprozesskommunikation (IPC) im Userspace laufen
- Die Isolation von Subsystemen bietet drei Vorteile
- Sicherheit: Eine Schwachstelle in einem einzelnen Treiber kann einem Angreifer nur die Zugriffsrechte dieses Subsystems oder Treibers geben, nicht die des gesamten Systems
- Zuverlässigkeit: Ein Absturz eines Subsystems betrifft nur diesen Teil, nicht das gesamte System
- Modularität: Sie verringert die Last für das Linux-Kernel-Team, alle Hardware-Treiber zu mergen und sogar das interne Verhalten jedes Chips prüfen zu müssen
- Wenn Windows ein Mikro-kernel-System gewesen wäre, hätte der CrowdStrike-Bug womöglich nur die Erfassung von Telemetriedaten einiger IT-Sicherheitsverantwortlicher gestoppt
Frühere Performance-Grenzen und die IOMMU-Lösung
- In früheren Mikro-kerneln konnten Userspace-Prozesse nicht direkt auf bestimmte Geräte zugreifen, weshalb für jede Operation System Calls und Kontextwechsel nötig waren; teure Locks und Speicherkopien kamen hinzu
- Mach verlagerte wegen Performance-Problemen Userspace-Prozesse schrittweise in den Kernel und näherte sich am Ende einem gewöhnlichen monolithischen Kernel an
- Heutige PCs sind seit etwa zehn Jahren standardmäßig mit einer IOMMU ausgestattet; zusammen mit Shared Memory kann sie auf dem Normalpfad bei ausreichend vielen Cores Kontextwechsel vollständig eliminieren
- Wenn man etwas Latenz akzeptiert, lassen sich Kontextwechsel auch insgesamt nahezu vermeiden
- Ein Scheduler auf Basis von Virtualisierungstechnik kann ähnlich wie der Xen-Hypervisor aufgebaut werden
- Der Zugriff auf I/O-Geräte wird von der IOMMU-Hardware verwaltet
- IPC lässt sich implementieren, indem zwischen Prozessen gemeinsame Buffer zugewiesen und atomare Integer-Compare-and-Swap-Operationen bereitgestellt werden
- Der gemeinsame Buffer wird als Command Queue in Form eines Ringbuffers verwendet, wobei Start- und End-Pointer atomar aktualisiert werden
- Auf dem Normalpfad können asynchrone Nachrichten ohne Kontextwechsel, Kopien zwischen Adressräumen und Locks übertragen werden; das Verfahren ist auch bei GPU-Treibern weit verbreitet
Bibliotheksaufbau und Nutzung bestehenden Codes
- In einer Umgebung, in der Prozesse VM-Gäste sind, können Shared Libraries beim Programmstart gelinkt werden; Funktionen, die nicht in anderen Prozessen laufen müssen, lassen sich lokal nach dem Exokernel-Ansatz ausführen
- In der heutigen Welt, in der Anwendungen im Electron-Stil ihre eigenen Betriebssystem-Komponenten mitliefern, sind duplizierte Bibliotheken im Speicher nicht mehr ein so großes Problem wie vor 30 Jahren
- Die wichtigsten Grundlagen für eine Implementierung existieren bereits
- Xen bringt den Großteil der für die Hypervisor-Schicht nötigen Funktionen mit
- Netzwerk- und Dateisystem-Server lassen sich wie bei Mach aufbauen, dabei kann Code aus FreeBSD übernommen werden
- DRM basiert bereits auf asynchronen Command Buffers, sodass das Linux-Grafiksubsystem im Userspace laufen kann
- Aus praktischen Gründen ist auch eine Konfiguration möglich, in der Display-Server und Grafiksubsystem im selben Prozess laufen
1 Kommentare
Lobste.rs-Meinungen
Der Grund, warum Linux alle Treiber enthält, ist, dass es keine stabile API für Kernel-Module außerhalb des Baums gibt; dafür ist ein Mikrokernel nicht zwingend nötig
Ich meine mich zu erinnern, auf der LKML Beschwerden gesehen zu haben, dass selbst unter der Annahme, alle Linux-Treiber in den User Space zu verlagern, Änderungen an internen APIs schwieriger würden
Sind Kernel aus der L4-Familie nicht als schnell bekannt? Ich frage mich auch, wie es bei Redox OS oder Fuchsia aussieht
Genode unterstützt mehrere Kernel, liefert aber auf seL4 und ähnlichen Systemen lächerlich schlechte Performance. Als Kollegen versucht haben, eine Linux-VM zu booten, wurde nur 32 Bit unterstützt, und selbst ein halbwegs vollständiger Bootvorgang dauerte mehrere Minuten
Dass ein Genode-Fork des NOVA microhypervisor die Standardplattform ist, hat tatsächlich den Grund, dass er funktioniert und die Performance ausreichend ist
Da ein Ringpuffer verwendet wird, könnte ein zweiter Kontextwechsel entfallen, wenn der Empfänger bereits auf einem anderen Core läuft. Das Interpretieren von Nachrichten ohne Kontextwechsel könnte die Angriffsfläche jedoch übermäßig vergrößern, weil der Empfänger die Nachricht selbst validieren müsste; etwas abmildern ließe sich das womöglich mit einer vom Kernel bereitgestellten dynamischen Bibliothek
Ich bin kein Experte, aber mir scheint, dass der Originaltext einige wichtige Überlegungen auslässt
QNX galt als schneller Mikrokernel, daher würde mich interessieren, was dort richtig gemacht wurde
Früher war ich zusammen mit einem Freund von der Eleganz von Mikrokernen, besonders QNX, fasziniert und habe damit ein FireWire-basiertes Videoverarbeitungsproblem umgesetzt. Der Code war einfach und elegant, aber entsetzlich langsam. Als wir damals dem 1394-Treiber unter Linux in etwa 12 Stunden DMA-basierte isochrone Übertragung hinzugefügt hatten, wurde die Performance deutlich besser, und dadurch verschwand auch die Skepsis in der Firma gegenüber Linux für optische Sortieranlagen
Das Ideal von QNX, Mikrokernen und Message Passing ist weiterhin großartig, aber um sich breit durchzusetzen, müssten die Kosten der Datenübertragung zwischen Prozessen deutlich sinken
Heute baue ich Webanwendungen mit Elixir und genieße dabei dieselbe Prozessisolation, mit der QNX geworben hat. Für Aufgaben ohne kritische Performance wie optische Verarbeitung ist das in Ordnung, aber Elixir/BEAM hat beim Problem der Datenkopien dasselbe Thema
Auch wenn Mach Komponenten nicht vollständig so unabhängig machen konnte wie ursprünglich gedacht, ist es wohl kein gewöhnlicher monolithischer Kernel geworden, und ich habe gehört, dass seine Architektur weiterhin Vorteile bietet
Bei klassischen POSIX-Dateilisten-Benchmarks, bei denen für jeden Eintrag
readdir()undstat()aufgerufen werden, sind Mikrokernel zwangsläufig im Nachteil. Verwendet man jedoch Batching-APIs wieio_uring, um die Häufigkeit von Systemaufrufen zu senken, ist hohe Latenz vielleicht keine so große SchwächeAuch Linux kann der Leitungsgeschwindigkeit nicht folgen, wenn für jedes Netzwerkpaket ein Systemaufruf erfolgt. Batching ist sowohl bei Linux als auch bei Mikrokernen wichtig
Ein interessanter neuer Vertreter in diesem Bereich ist HongMeng, leider jedoch proprietäre Software
Solange die Kosten der Datenbewegung nicht um mehr als eine Größenordnung sinken, scheint es schwer, dass Mikrokernel ausreichend konkurrenzfähig werden
Theoretisch sind sie elegant und sauber, aber die Realität ist komplex, und um mit dieser Komplexität umzugehen, muss vielleicht auch der Kernel bis zu einem gewissen Grad komplex sein
Ich mag die richtige Architektur, aber ich denke, dass für die dominante Stellung von Linux auch sekundäre Faktoren jenseits der reinen Technik eine große Rolle gespielt haben. Ich würde gern einen Text lesen, der das aus mehreren Blickwinkeln analysiert