Konzeptionelle Mängel von Unix
von Frank Klemm (Frank.Klemm@schnecke.offl.uni-jena.de)

Unix ist als schwer administrier- und bedienbar verschrien. Als Ursache wird die hohe Komplexität des Systems genannt. Leider ist das nur die halbe Wahrheit. Auch Fehler und Unzulänglichkeiten im System sowie unzweckmäßige Auslegungen von Komponenten des Kernels und von Systemkommandos tragen in erheblichen Maße dazu bei. Der Artikel zeigt an Hand von auffälligen Beispielen, was an Unix geändert werden muss, damit es gegenüber anderen Betriebssystemen (im Desktopbereich) mittelfristig bestehen kann.

Inhalt

Übersicht
Konfiguration von Unix
Die Bildschirmansteuerung
    Eingabe
    Ausgabe
Schlechter Zustand vieler Programme
Schlechtes Design des Zusammenspiels von Komponenten
Fehlende Einsicht in die Probleme, die Unix-kompatible Betriebssystem
haben
Weitere Wünsche
Lösung der Probleme
    Systemkonfiguration
    Konsolenansteuerung
    Programme/Programmpakete
    Ideologische Probleme

Übersicht

Ich bin das erste mal mit Unix vor elfeinhalb Jahren in Berührung gekommen, mit Linux vor dreieinhalb Jahren, seitdem nutze ich es für die meisten Probleme als Arbeitsbetriebssystem. Nach über drei Jahren sollte man die meisten auftretenden Probleme ohne großen Zeitaufwand beheben können. Leider ist das nach meinen Beobachtungen selten der Fall. Man stolpert dauernd über Probleme, die sich als ungewöhnlich zeitintensiv herausstellen, die sich prinzipiell nicht sauber oder nur durch Tricks, die mit dem eigentlichen Problem nichts zu tun haben, lösen lassen.

Die sich mir in den Weg stellenden Schwierigkeiten habe ich in den letzten sechs Monaten aufgeschrieben und versucht zu systematisieren. Wie ich feststellte, lassen sich viele davon auf wenige Ursachen zurückführen. Die wichtigsten werden im Folgenden erläutert.

Die Hauptprobleme sind:

  1. nicht zeitgemäßer Aufbau der Konfiguration des Betriebssystems
  2. nicht zeitgemäße Ansteuerung des Benutzerinterfaces
  3. schlechtes Design von Programmen und Schnittstellen zwischen Programmen, fehlende Standardisierung
  4. schlechter Zustand von Programmen und deren Dokumentation
  5. fehlende Einsicht in Probleme von Linux als Unix-Betriebssystem

Der Schluss des Artikels wird dem Thema gewidmet, wie man prinzipiell zur Lösung solcher Probleme vorzugehen hat.

Konfiguration von Unix

Die Konfiguration von Unix erfolgt in der Regel durch viele kleine ASCII-Dateien, die im Verzeichnis /etc/ oder personenbezogen im Heimverzeichnis stehen. Leider ist dies nicht die ganze Wahrheit.

Es gibt noch viele andere Stellen, an denen Konfigurationsinformationen abgelegt bzw. eher verborgen sind:

Besonders die eincompilierte Parameter sind hochgradig problematisch. Sie sind häufig nicht einmal dokumentiert, ihr Vorhandensein weniger einem Designprozess als mehr einem in der Vergangenheit schnell zu behebendem Problem zu verdanken.

Desweiteren gibt es folgende Probleme:

Weiterhin werden folgende weitere Fehler gemacht:

In Zusammenhang mit Fehlern in der Dokumentation und fehlenden Fehlermeldungen ist das tatsächliche Verhalten fast nur durch Quellenanalyse feststellbar. Das gilt selbst für Programme mit ansonsten guter Dokumentation.

Nur:

Außerdem ist man dadurch gezwungen, sich an der konkreten Implementierung statt an der Spezifikation bei der Konfiguration zu orientieren. Das ist falsch und fehlerträchtig. Fehler mit strace oder strings zu suchen, ist ein Anzeichen eines wenig transparenten Systems.

Desweiteren treten folgende Probleme auf:

Lösen ließe sich das Problem zum Beispiel durch ein zentrales Datenbankmanagmentsystem, das die Verwaltung der Systemkonfiguration übernimmt. Dies kommt der Unix-Philosophie entgegen, wo es für alle Aufgaben genau ein Programm gibt, das sich genau auf eine Aufgabe, die es dafür richtig beherrscht, beschäftigt. Dieses eine Programm praktisch fehlerfrei zu bekommen, ist möglich. Bei vielen Programmen ist es praktisch unmöglich.

Realisiert wurde dieses Prinzip u.a. bei AIX und HP-UX.

MS-Windows 9x/NT hat eine Konfigurationsdatenbank. Dabei wurden etliche Fehler gemacht, die einer zentralen Konfigurationsverwaltung einen sehr schlechten Ruf einbrachten:

Die Bildschirmansteuerung

Eingabe

Die Tastaturschnittstelle stammt aus einer Zeit, in der vor allem mit seriellen Terminals gearbeitet wurde. Cursortasten waren Luxus. Mäuse gab es außer für Spezialanwendungen nicht. Erweiterungen erfolgten (ähnlich wie INT10 unter MS-DOS) von unten nach oben.

Dadurch ergeben sich folgende Probleme:

Ausgabe

Hier gibt es folgende Probleme:

Schlechter Zustand vieler Programme

Die meisten Programme existieren seit Jahrzehnten. Sie sind seitdem teilweise von vielen verschiedenen Personen erweitert und modifiziert worden. Zum Teil mit und zum Teil ohne Verständnis des gesamten Programms. Auffällig sind folgende Dinge:

Trostpflaster: Etliche Programme sind sehr gut designt und haben ein sehr gutes Laufzeitverhalten (Beispiel: grep).

Schlechtes Design des Zusammenspiels von Komponenten

Ein großer Teil der Unix-Programme ist über Jahre hinweg von vielen verschiedenen Personen modifiziert und erweitert worden, wenn weitere Aufgaben anstandenn. Oftmals ist nur die anstehende Aufgabe gelöst worden, ohne sich zu fragen, wie man mit einem besseren Konzept alle Aufgaben dieser Art lösen könnte. Auf diese Weise sind zu viele Programme im Umlauf, die sich bei genauer Analyse als Flickenteppich heraustellen. Solange diese Programme nur lose im System verankert sind, kann man sie wegwerfen und vollständig neu programmieren. Leider geht das häufig nicht, weil eben diese Programme mit genauso verhunzten Programmen zusammenarbeiten, die ein sauberes Design verhindern. Andere Fehler haben sich als Standard etabliert oder sind fest im Kernel verankert.

Fehlende Einsicht in die Probleme, die Unix-kompatible Betriebssystem haben

Neben den programmtechnischen Problemen von Unix gibt es noch die folgenden:

Weitere Wünsche

Lösung der Probleme

Wenn man ein (aufwendigeres technisches) Produkt zu entwerfen oder eine (aufwendigere technische) Aufgabe oder Problem zu lösen hat, mit dem man sich schon länger beschäftigt hat, und bei dem Qualität im Vordergrund steht, dann sind folgende Dinge nicht zu machen:

Sondern es ist folgendermaßen vorzugehen:

  1. Es sind alle gewünschten (nach außen sichtbaren) Eigenschaften und alle unerwünschten (nach außen sichtbaren) Eigenschaften in verschiedenen Kategorien (unbedingt notwendig, dringend gewünscht, gewünscht, gern mitgenommen) zu sammeln und in weitem Kreise zu diskutieren. Die Analyse schon bekannter Lösungen mit all ihren Fehlern sind i.A. sehr hilfreich. Die Lebensdauer des Produktes ist dabei zu berücksichtigen (möglich: von einem Jahr bis zwanzig bis dreißig Jahre).

    Manche nennen so etwas auch Lastenheft. Es ist allerdings kein Lastenheft, da es allgemeiner ist und mehr dem prinziellen Finden einer Lösung dienen soll.

  2. Es ist zu analysieren, ob es nicht schon Produkte gibt, die diese geforderten Eigenschaften weitgehend erfüllen. Ist das der Fall, kann man hier aufhören.

  3. Erst dann kann man anfangen, sich Gedanken über konkret mögliche Implementierungen und Schnittstellen zu machen. Dabei sind dann solche Dinge zu klären, welche Eigenschaften niedriger Kategorien aus dem Lastenheft entfernt werden, weil das Problem durch sie nicht lösbar oder viel zu komplex wird. Mathematische Exaktheit sollte hier selbstverständlich sein, um möglichst viele Probleme im Vorfeld zu klären.

    Beachte: Ein Problem ist nicht dann nicht lösbar, wenn einem in fünf Minuten keine Lösung einfällt. Ein Problem ist nicht dann lösbar, wenn einem sofort eine Idee kommt, wie man es lösen könnte!

  4. Die Schnittstellen sind in weitem Kreise zu diskutieren. Diese sind es, mit denen sich die nächsten Generationen rumzuärgern haben. Alternative interne Implementierungen sind jederzeit möglich, bei Schnittstellen ist das unmöglich!

    Bemerkung: Für die Phasen (3) und (4) ist eine Testimplementation erforderlich. Nur durch eine solche ist es möglich, sich später nicht mit unpraktischen Schnittstellen rumzuschlagen, da man merkt, wo es Probleme gibt. Eine leicht geänderte Schnittstelle kann ohne Leistungsverlust das Programm erheblich vereinfachen. An diese Testimplementation wird keine Forderung gestellt, außer dass sie geht, d.h.:

    Diese Testimplementation ist nach Erstellung des Lastenheftes irreversibel wegzuwerfen. Das Nutzen von leistungsfähigen Tools ist erwünscht (z.B. yacc, lex)

  5. Aufstellen einer Präambel, was das Programm macht (drei bis fünf Sätze). Exakte Spezifikation des Lastenhefts (dies ist das Wertvollste an diesem gesamten Vorgehen).

  6. Dann haben Hand in Hand nach Lastenheft (z.B. auch von einer ganz anderen Person) zu erfolgen:

    Dokumentation - Implementation - Test

    Bemerkung: Die Programmierung von Tools hat nach deren Dokumentation zu erfolgen. Nur dann erhalte ich eine relativ kurze, richtige und konsistente Dokumentation. Andernfalls ist die Dokumentation häufig nur der verzweifelte Versuch, die Syntax des vor Monaten programmierten nachträglich zu rechtfertigen. Fehler sind im Programm abzuändern, nicht in der Dokumentation.

Nachteil ist, dass das Ganze etwas länger dauert, dass es (am Anfang) deutlich mehr Aufwand bereitet, dass die Hemmschwelle viel höher ist, so mit einer Aufgabe anzufangen. Desweiteren steht es mit den Grundprinzip von Unix (Schneller Entwurf eines Prototypen) im scheinbaren Widerspruch. Beide Wege haben ihre Daseinsberechtigung. Einige Kriterien für beide Methoden sind:

Schneller Prototyp:

Aufwendiges Design:

Was heißt das für die oben genannten Probleme?

Trostpflaster: Saubere Konzepte lassen sich erfahrungsgemäß wesentlich einfacher implementieren. Die Programme werden kürzer, schneller und leistungsfähiger. Es entfällt das dauernde Aufbohren mit Features, die urplötzlich als Wünsche aus allen Richtung auftauchen. Die Dokumentation wird kürzer und verständlicher.

Anschließend nur einige Kurzbemerkungen:

Systemkonfiguration

Die Entwicklung wird in die Richtung gehen, dass man sich weiter vom physischen Medium entfernt.

  1. Die elementarsten Konfigurationsinformationen sind roh auf dem Medium abgelegt (Partitionstabelle, Bootlader).

  2. Weitere wichtige Informationen sind eine Ebene höher untergebracht, im Dateisystem (/etc/fstab bzw. /etc/mount.conf, /etc/inittab bzw. /etc/init.conf, /etc/lilo.conf).

    Bemerkung: Üblich, seit Dateisysteme üblich geworden sind.

  3. Nicht zum Systemstart notwendige Information wird in eine weiter oben liegende Abstraktionsebene (Datenbankserver) übergehen.

    Bemerkung: Üblich, seit Datenbanken üblich geworden sind.

  4. Zur weiteren Entwicklung empfehle ich Doc Emmett L. Brown zu fragen

Konsolenansteuerung

  1. Moderne, ereignisgesteuerte Eingabeschnittstelle, die mir pro Eingabe durch HIDs (Human Interface Device) eine definierte Struktur mit allen Informationen übergibt, kein Dekodieren von Bit- und Byteströmen.

    Unterstützung von vielen verschiedenen Eingabegeräten (Tastaturen, Mäuse, Joysticks, Barcodeleser, Graphiktabletts, usw.) über eine Schnittstelle (damit keine Fehler durch unterschiedliche Laufzeiten der einzelnen Datenströme über Netzwerke).

    Übertragung von

    in orthogonaler Form.

  2. Schaffung eines Standards mit sehr guter Erweiterbarkeit, dabei keine Fehler auf der Applikationsebene bei unbekannten Erweiterungen (unbekannte Tasten liefern einfach keine Codes).

  3. Unabhängigkeit der einzelnen Systemrufe, d.h. keine unnötigen Wechselwirkungen zwischen früheren Ausgaben.

  4. Kompatiblität durch eine Hintergrundprogramm, welches eine Schnittstelle der alten Art zur Verfügung stellt.

Programme/Programmpakete

Mut zum Wegwerfen und Neuimplementieren, wenn man den Überblick verloren hat oder keine saubere und wasserdichte Implementierung mehr möglich ist. Man tut sonst sich und anderen keinen Gefallen.

Wegkommen von den 99,9% fehlerfrei arbeitenden Programmen. Auch wenn das die gängige Philosophie ist ("What the hell is the point of throwing away something that works 99.9% of the time...", Linus Torvalds), ein solcher Fehler macht ein System nicht mehr deterministisch, viele davon führen zu einem System, das nur noch von damit vertrauten bedient werden kann, das aber keinesfalls mehr ein elitäres System darstellt.

Beachte: Ein Herzschrittmacher mit einer Zuverlässigkeit von 99,99% steht 52 Minuten im Jahr still.

Außerdem verführt es zum Erstellen weiterer fehlerhafter Programme, zum einen, weil es dann üblich ist darüber hinwegzusehen, zum anderen, weil die Fehlerursache nicht mehr lokalisierbar ist. Ist es mein Bug oder die Auswirkungen eines fremden Bugs?

Ideologische Probleme

Nur eine Bemerkung zum Schluss: Die Lösung ökonomischer Fragen mit ideologischen Antworten ist ein schon mehrfach gescheitertes Modell. Das sollte man beim Entwurf immer im Gedächtnis behalten. Es kommt nicht darauf an, eine andere Lösung wie andere zu finden, sondern eine möglichst optimale Lösung.