Verteilte Betriebssysteme

Geschwurbel von Daniel Schwamm (02-03/1994)

Inhalt

1. Einführung

1.1. SISD- und MIMD-Rechnerarchitektur

Am Anfang der Informationstechnologie gab es nur den Von-Neumann-Rechner mit seiner Single Instruction Single Data-Architektur (SISD): Instruktionen und Daten werden hier aus demselben Speicher geladen, von einer Kontrolleinheit decodiert und von nur einem Prozessor verarbeitet. Später wurde die Rechnerarchitektur Multiple Instruction Multiple Data (MIMD) entwickelt, bei der mehrere Prozessoren parallel arbeiten, die jeweils einen eigenen Strom an Daten und Instruktionen besitzen. Je nachdem, ob die Prozessoren über einen gemeinsamen Speicher kommunizieren bzw. jeder einen separaten unterhält, spricht man von Multiprozessorsystemen (z.B. die Cray-Rechner) bzw. Multicomputersystemen, zu denen im weiteren Sinne auch die herkömmlichen Rechnernetze gehören.

1.2. Rechner-Vernetzung

Rechnernetze sind stark im Wachstum begriffen. Die Hardware (HW) der Computer, Knoten und Übertragungsmedien verfügt über immer mehr Leistungskapazität bei gleichzeitig fallenden Preisen. Die Vernetzung der Welt ist daher ein Prozess, der sich in den kommenden Jahren sicher noch explosionsartig weiter entwickeln wird.

1.3. Definition verteilte Betriebssysteme?

Den Höhepunkt der bisherigen Rechnernetztechnik stellt die Entwicklung sogenannter "verteilter Betriebssysteme" dar, die von ihrer Architektur her den Multiprozessorsystemen gleichen. Eine genaue Definition des Begriffs "verteiltes Betriebssystem" gibt es zwar nicht. Wir halten uns in dieser Arbeit jedoch an die folgenden allgemein akzeptierten Charakteristiken:

Ein verteiltes Betriebssystem verfügt über mehrere, voneinander unabhängige Knotenrechner, die jeweils mit mindestens einer CPU ausgestattet sind. Zwischen den Knoten gibt es ein Verbindungsnetz, über welches die Knoten miteinander kommunizieren können. Auf allen Knoten kommt derselbe Betriebssystemkern zum Einsatz. Stürzt ein Betriebssystem auf einem Rechner ab, kann der Anwender vom gleichen Rechner aus über einen anderen Rechner in transparenter Weise weiterarbeiten - das Gesamtsystem verliert dabei nur so viel an Leistung, wie der abgestürzte Rechner durch seine CPU dazu gegeben hatte. Als MIMD-Multiprozessor-Architektur verfügen alle Knoten über einen gemeinsamen Speicherbereich, was hilft, Techniken zu entwickeln, die die Single Point of Failure-Problematik herkömmlicher Rechnernetze ausschliessen und Verteilungstransparenz ermöglichen.

1.4. Verteilungstransparenz

Verteilungstransparenz ist die höchste in einem Netzwerk erreichbare Transparenzstufe. Sie sagt aus, dass ein Knotenprozess nicht explizit angeben muss, wo sich ein anderer Prozess, mit dem er kommunizieren muss, innerhalb des verteilten Betriebssystems befindet - dieses Wissen wird quasi implizit vom verteilten Betriebssystem gestellt. Verteilungstransparenz umfasst damit im Einzelnen folgende Dinge:

  • Zugriffstransparenz: Zugriff auf entfernte Daten geschieht in gleicher Weise wie ein Zugriff auf lokale Daten.
  • Lokationstransparenz: Zugriff auf Daten möglich, ohne Wissen um deren genauen Speicherort.
  • Replikationstransparenz: Zugriff auf Daten ohne Wissen um evtl. vorliegende konsistente Mehrfachspeicherung der Daten möglich.
  • Fragmentierungstransparenz: Zugriff auf bestimmte Daten ohne Wissen um evtl. vorliegende Fragmentierung der Daten möglich.

Die oben aufgeführten Transparenzeigenschaften unterscheiden sich deutlich von denen, die ein herkömmliches Netzbetriebssystem anbietet. Bei einem nicht-verteilten Betriebssystem kann zwar jeder Rechner im Netz ein anderes Betriebssystem betreiben, es muss jedoch jedem Prozess explizit mitgeteilt werden, wo er welche Ressourcen finden kann. Stürzt ein nicht-verteiltes Betriebssystem auf einem Rechner ab, kann dieser Rechner nicht mehr an der Kommunikation teilnehmen (im Gegensatz zu verteilten Betriebssystemen, wo dies nur zu einer allgemeinen Leistungsminderung im Netzwerk führt). Das Wichtigste aber ist, dass nicht-verteilte Betriebssysteme über keine Verteilungstransparenz verfügen, auch wenn sie diese Problematik durch graduell verschiedene Tools bzw. Dienste zu umgehen suchen.

1.5. "Verteilungstransparenz" bei UNIX

Sehen wir uns das nicht-verteilte Betriebssystem UNIX an. Es versucht, über folgende Methoden eine Art Verteilungstransparenz zu erreichen:

  • Dateisystem: Das Dateisystem von UNIX erlaubt das Kopieren von Dateien innerhalb des lokalen Rechnernetzes unter Angabe des Pfadnamens (keine Ortstransparenz gegeben).
  • Network-Disk-Server: Ein Diskettenserver, der es mehreren (diskless) Workstations ermöglicht, über ein entferntes Diskettenbetriebssystem Daten auszutauschen. Auch hier muss der Pfadname vollständig angegeben werden.
  • Network File System (NFS): Ein verteiltes Dienstprogramm (in UNIX integriert), welches die Montage fremder Verzeichnisse in das eigene Verzeichnis ermöglicht (um genau zu sein: Das Mount-Protokoll ist ein eigenständiges Programm, denn NFS stellt eigentlich nur Lese- und Schreiboperationen zur Verfügung). Nach der Montage kann fast von Lokationstransparenz und Zugriffstransparenz gesprochen werden, aber eben nur fast: Die Pfadnamen des eigenen Directory-Baums müssen weiterhin angegeben werden. Schwerwiegender ist aber, dass vor dem Montieren keine Ortstransparenz vorliegt, da der Benutzer wissen muss, wo sich das zu montierende Verzeichnis finden lässt. Auch unterstützt NFS keine Transaktionen, da es mit zustandslosen Servern (svw.) arbeitet. Unter Verwendung der UDP- bzw. TCP-Protokolle gestattet es aber immerhin Remote Procedure Calls (RPC) von pointerlosen, idempotenten Funktionen, die über Timeout- und Duplikationstechniken sogar zuverlässig arbeiten können.

2. Interaktionsmuster und Prozessorganisation

Interaktionsmuster geben an, wie sich Prozessoren koordinieren können, um gemeinsam ein Problem bearbeiten zu können.

2.1. Sechs verschiedene Methoden der Interaktion

  1. Pipelining: Bei diesem Interaktionsmuster empfängt ein Prozess F einen einzelnen Eingabewert x, bearbeitete diesen und gibt das Ergebnis F(x) aus oder macht etwas anderes damit. Zu beachten ist: Die Verbindung über Pipelines ist unidirektional, d.h., will F das Ergebnis F(x) irgendwo anders hin senden, so muss er dazu eine neue Pipeline aufbauen.
    PROCESS F;
    LOOP DO
          RECEIVE(x);
          ...
          SEND(F(x));
    END
    
  2. Peer-to-Peer-Interaktionsmuster: Hier kommunizieren zwei gleichwertige Prozesse miteinander im Duplex-Betrieb. Normalerweise wird dies ausgenutzt, um zuverlässige Verbindungen zwischen den Partnern aufzubauen, in dem z.B. ein vollständiges (OSI-)Handshake-Verfahren durchgeführt wird.
    PROCESS P1;                    PROCESS P2;
    LOOP DO                        LOOP DO
          SEND(request);                 ...
          RECEIVE(confirm);              RECEIVE(indication);
          ...                            SEND(response);
    END                            END
    
  3. Client/Server-Konzept: Bei diesem Interaktionsmuster kommunizieren zwei nicht-gleichberechtigte Partner miteinander. Der Client ist stets der Dienstleistungsempfänger und der Server stets der Dienstleistungsbetreiber. Es gilt auch: Ein Server bedient viele Clients, ein Client benutzt nur wenige Server. Diese Art der Kommunikation ist die in verteilten Betriebssystemen übliche.
    PROCESS Client (fordert aktiv)         PROCESS Server (wartet passiv)
    LOOP DO                                LOOP DO
       SEND(request);                         RECEIVE(request);
       ... wartet hier in der Regel           ...
       RECEIVE(reply);                        SEND(reply);
    END                                    END
    
  4. Heartbeat-Interaktionsmuster: Diese Art der Kommunikation wird häufig in Parallelrechnern eingesetzt. Sie arbeitet zweiphasig: In der ersten Phase senden z.B. die Prozessoren P1, P2 und P3 gleichzeitig Nachrichten an die Prozessoren P4, P5 und P6, und in der zweiten Phase senden P4, P5 und P6 gleichzeitig Nachrichten an P1, P2 und P3.
  5. Probe/Echo-Konzept: Dieses Interaktionsmuster wird häufig eingesetzt, wenn die Prozessoren hierarchisch (z.B. als Binärbaum) organisiert sind. Dabei gibt ein Elternknoten (ein Basisprozess) eine sogenannte Probe-Nachricht an seine Kinder weiter, die sie dann weiter an ihre Kinder leiten usw., bis sie schliesslich das Baumende/den Zielprozess erreicht haben und in verarbeitetet Form als Echo-Nachrichten den Baum wieder heraufsteigen.
    PROCESS Knoten Pi
    LOOP DO
          RECEIVE(probe) FROM parent
          SEND(probe) to child 1, ..., child n;
          RECEIVE(echo) from child 1, ..., child n;
          SEND(echo) to parent;
    END
    
  6. Token-Passing-Methode: Bei diesem Interaktionsmuster koordinieren sich Prozessoren dadurch, dass stets nur der Nachrichten versenden darf, der im Besitz des Tokens ist. Jeder kann das Token nur für kurze Zeit halten und muss es dann weitergeben, sodass kein Prozessor über längere Zeit das ganze Kommunikationsmedium blockieren kann (es geht also "fair" zu!). Unter Umständen ist es auch möglich, dass sich mehrere Token im System befinden, sodass durchaus auch parallel Nachrichten versendet werden können.
    PROCESS Pi
    LOOP DO
          RECEIVE(token);
          ...
          SEND(token);
    END
    

2.2. Vier verschiedene Methoden der Server-Organisation

Oben haben wir gesehen, über welche Interaktionsmuster Prozesse Nachrichten austauschen können. In verteilten Betriebssystemen ist davon auszugehen, dass sich die Prozesse nicht auf den gleichen Rechnern befinden, daher müssen die Prozesse so organisiert werden, dass sie über ein LAN (u.U. auch über ein WAN) hinweg miteinander kommunizieren können. Insbesondere muss auch dafür gesorgt werden, dass alle Rechner im LAN gleichmässig ausgelastet werden. Man spricht hier von Prozessorganisation oder besser: Serverorganisation, weil den verteilten Betriebssystemen fast immer das Client/Server-Interaktionsmuster zugrunde liegt. Verschiedenen Methoden der Server-Organisation wollen wir uns nun einmal betrachten.

  1. Work-Sharing-Server: Bei dieser Technik verfügt jeder Serverrechner im LAN über eine bestimmte Anzahl von Ports, also Netzzugängen, denen jeweils genau ein Serverprozess zugeordnet ist. Jeder Client braucht hier also nur die Serveradresse zusammen mit der Portnummer ins LAN einzugeben und schon bekommt er Zugriff auf einen bestimmten Dienstprozess des Serverrechners. Dies hat allerdings den schweren Nachteil, dass jeder Serverprozess nur genau einmal instanziiert werden kann, weil ihm ja nur eine Portnummer zur Verfügung steht.
  2. Load-Sharing-Server: Bei dieser Technik verfügt der Serverrechner über einen Listener, der alle Port-Eingänge abhört. Kommt ein Verbindungswunsch eines Clients an einem Port an, so erzeugt der Listener einen Link-Handler für den gewünschten Dienst (der daraufhin erst instanziiert wird) und weist ihm die Portnummer zu.
    PROCESS Listener              PROCESS Handler
    LOOP DO                       DO
          RECEIVE(request);           RECEIVE(port-id);
          CREATE(handler);            CALL(service-process);
          ...                         SEND(reply);
    END                           END
    
  3. Server-Replikation: In grösseren LANs ist es üblich, dass mehrere Server-Rechner eingesetzt werden, die jeweils die gleichen Dienste anbieten. Damit die Clients die Dienste von dem am wenigsten ausgelasteten Serverrechner ausgeführt bekommen, ist es nötig, einen Server-Server zu betreiben, den sogenannten Pool-Manager. Alle Anfragen (Requests) der Clients gehen also nicht an die Dienstserver, sondern an den Pool-Manager, der dann einen Server-Rechner bestimmt, der die gewünschte Antwort (Reply) liefern soll. Natürlich birgt diese Zentralisation wie immer die üblichen Probleme: Flaschenhals und Single Point of Failure.
  4. Client/Server-Kooperation: Bei dieser Methode sendet der Client seine Requests nicht an einen bestimmten Dienstserver oder Pool-Manager, sondern gibt sie für alle sichtbar (broadcast) ins Netz. Hier gibt es nun verschiedene Arten, wie mit dieser Broadcast-Nachricht verfahren wird. Einmal ist es möglich, dass die Clients sich damit untereinander abstimmen, wer welchen Server benutzen darf (client-kontrollierte Auswahl). Besser ist es aber, die Server selbst bestimmen zu lassen, wie sie auf die Broadcast-Anfrage reagieren sollen (serverkontrollierte Auswahl). Die Server kennen sich i.d.R. gegenseitig und können dadurch den jeweiligen Auslastungsgrad ermitteln, sodass sich stets der am wenigsten ausgelastete Server bei Client melden kann.
    PROCESS Client
    DO
          BROADCAST(wer ist frei?);
          RECEIVE(ACK von bestimmten server);
          SEND(request);
          RECEIVE(reply);
    END
    

2.3. Zu merken

Interaktionsmuster haben etwas damit zu tun, wie sich Prozesse untereinander Nachrichten zusenden. Prozessorganisation hat etwas damit zu tun, wie dafür gesorgt werden kann, dass alle Rechner im Netz gleichmässig ausgelastet werden können.

3. Kommunikationsmodelle

Im vorherigen Kapitel wurde beschrieben, über welche Interaktionsmuster sich Prozesse koordinieren können, um gemeinsam eine Aufgabe zu lösen. Als das wichtigste Interaktionsmuster wurde dabei das Client/Server-Konzept herausgestellt. Des Weiteren wurde gezeigt, wie sich die im Netz verteilten Serverprozesse gegenseitig organisieren, sodass die einzelnen Server-Rechner möglichst gleichmässig ausgelastet sind.

3.1. Primitive

In diesem Kapitel wenden wir uns der Nachrichtenart "Primitive" zu. Diese dienen dazu, aus einem (Client-)Prozess heraus einen anderen (Server-)Prozess zu erzeugen. Je nach Komplexität derartiger Primitive können die folgenden Kommunikationsmodelle unterschieden werden.

  1. Mitteilungsorientiertes Kommunikationsmodell: Bei diesem Modell können nur sehr einfache Primitive durch den Client gesendet werden, bei denen keine Rückantwort durch den Server erfolgt. Diese Primitive sind also unidirektionale Nachrichten. Ein Beispiel hierfür sind unquittierte E-Mails.

    Wenn Sender und Empfänger nicht synchronisiert werden, dann arbeitet der mitteilungsorientierte Sender nach dem "No-Wait-Send"-Prinzip, d.h., er sendete die Primitive ohne jede Verzögerung. Dies bedingt jedoch, dass der Empfänger entweder über Puffer verfügt oder ein "Busy-Waiting" durchführt. Evtl. kann auch im Netzwerk selbst ein Pufferung vorgenommen werden.

    Sind Sender und Empfänger synchronisierbar, dann arbeitet der Sender nach dem "Synchronization-Send"-Prinzip, auch "Rendezvous"-Prinzip genannt, weil sich hier Client und Server zu einem bestimmten Zeitpunkt treffen. Dazu benötigt der Empfänger keine Puffer (ausser evtl. zur Flusskontrolle).

  2. Auftragsorientiertes Kommunikationsmodell: Bei diesem Modell erhält der Client nach Sendung des Primitives ein Resultat von dem dadurch erzeugten Server-Prozess zurück. Die auftragsorientierten Primitive sind also duplexe Nachrichten. Ein Beispiel hierfür: Uhrzeit-Server.

    Im asynchronen Betriebsmodus arbeitet der auftragsorientierte Sender nach dem "Remote Service Invocation"-Prinzip. Hier kann der Client nach der Dienstanforderung weiterarbeiten und muss nicht warten, bis der Server die Antwort sendet (Nicht-Blockierung). Diese Technik wird allerdings in der Praxis kaum realisiert.

    Im synchronen Betriebsmodus arbeitet der Sender nach dem "Remote Procedure Call"-Prinzip. Hier arbeiten Primitive genauso wie Unterprogramme. Während das Unterprogramm (der Serverprozess) ausgeführt wird, blockiert das Hauptprogramm (der Clientprozess) so lange. Dies ist die meist benutzte Technik bei verteilten Betriebssystemen, wobei das erklärte Ziel völlige Transparenz ist, d.h., dass entfernte Unterprogrammaufrufe nicht von lokalen zu unterscheiden sein sollen. Allerdings erlauben Remote Procedure Calls nur sehr selten Pointer als Argumente.

  3. Transaktionsorientiertes Kommunikationsmodell: Bei diesem Modell können komplexe Primitive vom Client gesendet werden, die nur dann ein Resultat vom Server-Prozess erhalten, wenn sie zuvor vollständig abgearbeitet worden sind. Dadurch wird effektiv ausgeschlossen, dass halb ausgeführte Serverdienste irgendwelche unbeabsichtigten Seiteneffekte hervorbringen können. Ein Beispiel hierfür: Homebanking.

    Transaktionen zeichnen sich im Übrigen durch die folgende ACID-Eigenschaft aus:

    • Atomicity:: Sie arbeiten nach dem Alles-oder-Nichts-Prinzip.
    • Consistency: Sie gehen von einem konsistenten Zustand in einen anderen über.
    • Isolation: Sie eigen nur bei Erfolg Auswirkungen.
    • Durability: Ihr Erfolg geht nicht verloren.

3.2. Kommunikationsmodell-Varianten

Die oben aufgeführten Kommunikationsmodelle sind erheblich variierbar, wodurch sie sich optimal auf das jeweilige Subnet oder die zugrunde liegenden Rechnerkonfigurationen anpassen lassen. So können die Modelle z.B. sein:

  • gepuffert/ungepuffert, wobei eine alternative Pufferung beim Sender/Empfänger/Medium möglich ist. I.d.R. ist eine Pufferung nur bei nicht-blockierenden Knoten und also asynchronem Betrieb nötig.
  • atomic/zuverlässig/unzuverlässig, wobei folgende Fehlerklassen möglich sind:
    • maybe: Ein Paket kommt vielleicht nie am Ziel an.
    • at least once: Mindestens ein (Duplikat-)Paket erreicht Ziel.
    • at most once: Höchstens ein (Duplikat-)Paket erreicht Ziel.
    • exactly once: Idealisiertes "at most once".
  • direkt oder indirekt adressierend, d.h., der Client spricht einen Serverdienst direkt oder indirekt über einen Name-Server an.
  • blockierend/nicht-blockierend (i.d.R. identisch mit synchron/asynchron), d.h. der Client kann eventuell weiterarbeiten, während der Server den Dienst erfüllt.

Als Protokolle kommen üblicherweise Fensterprotokolle infrage (v.a. beim asynchronen Betrieb), die durch Wahl ihrer Fenstergrösse sehr anpassungsfähig sind. Bei einer Fenstergrösse von 1 hat man z.B. ein einfaches Stop-and-Wait-, bei grosser Fensterwahl dagegen ein recht komplexes Übertragungsprotokoll.

3.3. Zu merken

Kommunikationsmodelle haben etwas mit der Komplexität der nach dem Client/Server-Konzept austauschbaren Primitive zu tun. Die synchrone Variante des auftragsorientierten Kommunikationsmodells ist dabei das für verteilte Betriebssysteme am ehesten geeignete.

4. Namensverwaltung

In einem Rechnernetz haben folgende Objekte Namen: Rechner (Knoten), Prozesse und Benutzer.

4.1. Aufgaben der Namensgebung

  • Identifikation: Namen sollen existierende Objekte bezeichnen.
  • Indirektion: Namen sollen (dynamische) Objekte referenzieren.
  • Abstraktion: Namen sollen die Details vor dem Benutzer verbergen. Daher sind vor allem reine Namen (ohne Pfadangabe) beliebt, da sie transparenter als unreine Namen sind.

4.2. Namensformen

Namen müssen widersprüchliche Ziele ausbalancieren. Sie können sein:

  • unrein/rein, d.h. mit/ohne Ortstransparenz versehen. Bei reinen Namen fehlen die Pfadangaben, die ein Name-Server über seine Kontextinformationen herausfinden muss. Das hat den grossen Vorteil, dass Objekte mit reinen Namen migrieren können, ohne ihren Namen neu definieren zu müssen.
  • flach/hierarchisch/routingorientiert.
  • benutzerfreundlich/maschinengerecht, d.h., die ersten Namen sind i.d.R. hierarchisch und die zweiten Namen i.d.R. flach/routingorientiert aufgebaut. Meistens ist die eine Namensform über eine Abbildungsfunktion in die andere transformierbar - man spricht dann von Benutzernamen und Systemnamen.
  • statisch/dynamisch, d.h. stabil oder änderbar.
  • absolut/relativ, d.h. mit einem ganzen bzw. relativen Pfadnamen versehen.
  • direkt/indirekt, wobei Letzteres bedeutet, über Mailbox, Ports oder Links bestimmte Prozesse anzusprechen.

4.3. Erscheinungsformen global eindeutiger Namen

  • Bezeichner, die sowohl zeit- als auch ortstransparent sind. Z.B. "Drucke" für einen Serverdienst.
  • Identifikatoren, die zwar ortstransparent sind, dafür aber meistens nicht zeittransparent, z.B. eine Prozess-ID.
  • Adressen, die zwar nicht ortstransparent sind, dafür aber meistens zeittransparent, z.B. Ethernet-Adresse.

Die meisten Name werden letztlich auf Adressen abgebildet (über eine sogenannte Abbildungsfunktion). Dabei wird kontextabhängig-analytisch vorgegangen, d.h., der Name wird aufgespalten, wobei jeder Teil (jedes Attribut) einen anderen Rechnernetz-Kontext umfasst, abhängig davon, ob ein hierarchischer, routingorientierter oder sonstiger nicht-flacher Adressenaufbau vorliegt.

4.4. Name-Server

Name-Server sollen helfen, in verteilten Betriebssystemen globale Kontexte aufzubauen. Neben der Namensverwaltung führen sie üblicherweise auch die Authentifikation der Clients durch.

4.4.1. Organisation

  • Zentraler Name-Server: Ein Server verwaltet alle Namen im Netz, verfügt also über den (idealen) globalen Kontext.
  • Verteilter Name-Server mit ortsabhängigen Namen: Jeder Client ist auch Name-Server, der bei Broadcast-Calls reagiert, wenn er den gesuchten Namen im eigenen Kontext führt. Der Pfadname muss jedoch mit angegeben werden, d.h., ortstransparente Namen sind nicht möglich.
  • Voll verteilter Name-Server: Jeder Client ist auch Name-Server, der jeden beliebigen Namen auflösen kann. Ortstransparenz ist gegeben.
  • Verkettete Name-Server: In grossen Netzen empfiehlt sich diese Name-Server-Organisation. Jeder Name-Server verwaltet hier nur den Kontext von Namen, die er selbst generiert hat. Findet er bei einer Anfrage den gesuchten Namen nicht, werden andere Name-Server kontaktiert.

4.4.2. Methoden der Namensauflösung

Die Namensauflösung bei verketteten Name-Servern kann auf fünf Methoden geschehen:

  1. Chaining-Methode: Ein Name Agent-Prozess des Client-Rechners fragt den Name-Server seines Kontextes nach einem Namen. Findet dieser den Namen nicht, so fragt er den nächsthöheren Kontext-Name-Server. Findet dieser den Namen, so meldet er ihn dem ersten Name-Server zurück, der ihn dann dem Name Agent mitteilt, der ihn sich mittels internem Caching merkt. Findet er ihn nicht, verfährt er wie der erste Name-Server.
  2. Zuweisungsmethode (Referential Method): Bei dieser Methode erfährt der Name Agent bei Suchmisserfolg eines Name-Servers von diesem jeweils die Adresse des nächsthöheren Kontext-Name-Servers, den er dann selbst kontaktieren muss.
  3. Weitergabe-Methode: Hier hangelt sich die Suche ähnlich zu der Chaining-Methode immer höher in den Baum, bis der Name bei einem Kontext-Name-Server gefunden wird. Diesmal wird allerdings danach nicht mehr der Baum zurückgelaufen, sondern die bekannte physische Adresse des Name Agent direkt kontaktiert.
  4. Broadcast-Methode: Jeder Client bekommt den gesuchten Namen zugesendet und der richtige Client antwortet. Diese Methode wird z.B. im ARPA Internet durch das Address Resolution Protocol-Protokoll realisiert: Man fragt nach "Susanne" und erhält "129.55.210.111" zurück.
  5. Multicast-Methode: Nicht jeder Client, sondern nur jeder Kontext-Name-Server erfährt den gesuchten Namen und sieht nach, ob er ihn verwaltet. Wenn ja, meldet er sich beim Client.

4.4.3. Beispiele für Name-Server

4.4.3.1. X.500-Norm

Als Beispiel für einen Name-Server kann die X.500-Norm der CCITT angeführt werden. Dieser globale Directory-Dienst arbeitet mit einer verketteten Name-Server-Architektur, benutzt daher auch hierarchische Namen, die kontextuell folgendermassen aufgebaut sind: Country=a, Organisation=b, Fachbereich=c, Namen=d. Der Namen wird über die Multicast-, Chaining- oder Referential-Methode von User Agents und Directory Service Agents aufgelöst, obwohl hier aufgrund des geringeren Datenverkehrs und der kürzeren Name-Server-Blockierung sicher die Weitergabe-Methode die bessere wäre.

4.4.3.2. V-Kernel

Auch V-Kernel verfügt über einen Directory-Dienst für das Mailing. Es gibt drei Ebenen: Die hierarchische Ebene mit Kennung "gov", "edu", "de" usw., die administrative Ebene mit Kennung "info.uni-mannheim" und die operationale Ebene mit Kennung "Schwamm", "Bohn" usw. Nur der operationale Kontext wird von Privatbenutzern gewartet, die restliche Verwaltung obliegt der Telekom. Die Clients verfügen über einen Namenspräfix-Cache, um sich den Speicherort von Prozessen merken zu können. Da diese Caches laufend gewartet werden, können die Objektmanager der operationalen Ebene gefahrlos migrieren (z.B. nach einem Absturz).

4.5. Zu merken

Namen werden in verteilten Betriebssystemen i.d.R. durch Name-Server verwaltet. Als die Geeignetsten erscheinen uns dabei verkettete Name-Server, die zur Namensauflösung die Weitergabe-Methode praktizieren.

5. Schutzmechanismen und Sicherheit

In einem verteilten Betriebssystem sind die Benutzer, die Betriebsmittel und die Daten zu schützen. Alternativ kann entschieden werden, ob die Schutzmechanismen im Betriebssystemkern verankert werden oder ob sie dem zu schützenden Objekt beigefügt werden. Im ersten Fall muss von einem abhörsicheren Betriebssystem ausgegangen werden und im zweiten Fall von einem abhörsicheren Kommunikationssystem. Der zweite Fall scheint uns für ein verteiltes Betriebssystem bessere geeignet zu sein, da hier die Systemcalls zum grossen Teil über Remote Procedure Calls simuliert werden, die über das Subnet abgewickelt werden. Solche RPCs laufen über Client-/Server-Stubs ab, die über eine Broadcast-Nachricht bzw. einen Directory-Service das Linken zwischen den Ports übernehmen und z.T. auch noch eine einfache Datenrepräsentation über Kodierungsregeln erlauben.

5.1. Verfahren zur Absicherung verteiltes Betriebssystem

Es gibt viele Wege, ein verteiltes Betriebssystem sicher zu gestalten und vor Missbrauch zu schützen. Einige davon seien im Folgenden vorgestellt.

  1. Ein-Wege-Autorisierung: Der Benutzer muss sich dem System gegenüber als autorisierter Benutzer identifizieren. Hierfür eignen sich die klassischen Passwort-Verfahren.
  2. Zwei-Wege-Autorisierung: Der Benutzer und das System müssen sich gegenseitig als autorisiert zu erkennen geben. Dies schützt in erster Linie davor, dass "Login-Masken"-Programme den Benutzer täuschen können, die nur dazu dienen, die Passwörter der Benutzer abzufangen. Auch hierfür eignen sich die klassischen Passwort-Verfahren.
  3. Autorisierungsprozesse zu Beginn einer Computersitzung können nie ganz sicherstellen, dass nicht doch ein Unbefugter ins Netz hineinkommt. Sei es durch Zufall oder weil er ein Passwort geklaut oder erraten hat. Wirklich sensible Daten werden daher häufig noch über kryptologische Verfahren geschützt. Grob unterschieden werden hier zwei Arten:
    1. Symmetrische Verfahren: Codierung und Decodierung erfolgen über nur einen geheimen Schlüssel.
    2. Asymmetrische Verfahren: Codierung und Decodierung erfolgen über jeweils verschiedene Schlüssel.
  4. Sichere verteilte Betriebssysteme Müssen sich vergewissern, dass ein Client, der einen Dienst anfordert, dazu überhaupt berechtigt ist. Daher muss sich der Client dazu zuvor einer Authentifizierungsprozedur unterziehen. Hier existieren zwei Strategien:
    1. Der Client (Subjekt) weiss nicht, welche Rechte er auf welche Dienste (Objekte) hat, der Dienstserver kann dies jedoch über Zugriffsmatrizen feststellen unter dadurch u.U. eine Verbindung unterdrücken. Zuvor muss sich der Client bei einem Name-Server authentifiziert haben. Nur dann erhält er die Dienstserveradresse und die Port-ID für den gewünschten Dienst zurück. So kann sich kein Client als ein anderer ausgeben und den Dienstserver übers Ohr hauen.
    2. Der Client weiss, welche Rechte er auf welche Dienste hat, weil er für sie bestimmte Befähigungen (Capabilities) besitzt. Solche Capabilities sind im Prinzip alternativ implementierte Zugriffsmatrizen. Will er einen Dienst bei einem Server anzufordern, so authentifiziert er sich zuerst beim Name-Server und sendet diesem seine Capability zu. Nur wenn sie korrekt ist, rückt der Name-Server mit der Dienstserveradresse und der Portnummer für den gewünschten Dienst heraus.

    Auch wenn es nötig ist, dass die Capabilities fälschungssicher sein müssen, so empfiehlt sich die Capability-Methode doch eher als die Zugriffsmatrix-Methode, um einen Client dazu zu autorisieren, einen bestimmten Dienst nutzen zu dürfen.

5.2. Client-Autorisierung mit Beispielen

5.2.1. Einfacher Algorithmus

Wir wollen uns nun einen einfachen Algorithmus ansehen, der dafür sorgt, dass ein Server sicher sein kann, dass der Client auch genau der ist, für den er sich ausgibt (was natürlich nicht heisst, dass er auch jeden Dienst in Anspruch nehmen kann).

1. Der Client sendet dem Server die Message "Ich bin C", einmal im
   Klartext und einmal als Code.

2. Der Server codiert die Klartext-Message und vergleicht sie mit der
   Code-Message. Ist sie identisch, dann kannte der Client den geheimen
   Schlüssel.

Zwei Nachteile hat diese Methode: Sie birgt die Gefahr von Replies, d.h., ein Unautorisierter kann hier leicht die Client-Message abfangen und beim Server als die eigene ausgeben, wo er dann prompt den gewünschten Dienst erfüllt bekommt. Ausserdem muss hier jeder Server sämtliche Schlüssel führen.

5.2.2. Algorithmus mit einmaliger Nachricht

Um derartige Replies zu verhindern, kann man einmalige Nachrichten (z.B. Uhrzeiten) versenden, die ein Unautorisierter nicht codieren kann, da er den geheimen Schlüssel nicht kennt.

1. Client sendet "Ich bin C" an Server.

2. Der Server sendet eine einmalige Nachricht an den Client.

3. Der Client codiert die einmalige Nachricht und sendet sie zurück.

4. Server prüft, ob die einmalige Nachricht richtig codiert wurde.

Problematisch bleibt nach wie vor, dass jeder Server sämtliche Schlüssel der Clients kennen muss.

5.2.3. Einbindung von Autorisierungsserver

Hier kann man sich mit der Einführung einer dritten Instanz helfen, nämlich mit einem Autorisierungsserver.

1. Client sendet "Ich bin C" an Server.

2. Server sendet einmalige Nachricht an Client.

3. Client codiert einmalige Nachricht und sendet sie zum Server.

4. Der Server codiert einmalige Nachricht mit eigenem Schlüssel,
   sendet sie zum Autorisierungsserver.

5. Der Autorisierungsserver entschlüsselt die einmalige Nachricht
   zweimal, codiert sie dann mit dem Schlüssel des Servers und
   sendet sie diesem zu.

6. Der Server decodiert einmalige Nachricht und überprüft sie.

5.2.4. Asymmetrische Verfahren

Bisher haben wir nur symmetrische Verfahren betrachtet. Der letzte Algorithmus lässt sich jedoch mit asymmetrischen Verfahren (Public Key) noch etwas verfeinern.

1. Client sendet "Ich bin C" an Server.

2. Server sendet einmalige Nachricht an Client.

3. Client codiert die einmalige Nachricht mit seinem geheimen
   Schlüssel und sendet sie zum Server zurück.

4. Server fordert vom Autorisierungsserver den öffentlichen
   Schlüssel von C an und decodiert und prüft damit
   die geheime Nachricht.

Als Beispiel für das Public Key-Verfahren lässt sich das RSA-Kryptosystem nennen. Hier ist die Idee, dass öffentlicher und privater Schlüssel grosse Primzahlen sind, die miteinander dupliziert den Schlüssel zur Decodierung darstellen. Da es nun aber sehr schwer ist, eine solche Multiplikation wieder aufzubrechen, selbst dann, wenn einer der Schlüssel und der Kryptosystem-Programmcode bekannt sind (!), kann einer der Schlüssel ohne Gefahren öffentlich verfügbar sein.

5.3. Zu merken

Um verteilte Betriebssysteme sicher zu machen, muss das ganze Subnet abhörsicher gestaltet sein. Am besten ist, die Benutzer einer Zwei-Wege-Autorisierung zu unterziehen. Die Clients verfügen über Capabilities, die sie sich bei Name-Servern bestätigen lassen, die sie dann bei Erfolg weiter mit speziellen Dienst-Servern verbinden. Um sicherzugehen, dass die Clients die sind, als die sie sich ausgeben, empfiehlt sich die geheime Verschlüsselung einmaliger Nachrichten, zu deren Überprüfung sich der Name-Server dann jeweils beim Autorisierungsserver den öffentlichen Schüssel besorgen kann.

6. Prozessverwaltung

6.1. Prozessablauf

Prozesse laufen in Rechnern sequenziell oder nebenläufig ab. Für verteilte Betriebssysteme interessieren uns v.a. nebenläufige Prozesse. Hier unterscheiden wir:

  • Multiprogramming: Nebenläufige Prozesse benutzen eine CPU im Wechsel.
  • Multiprocessing: Nebenläufige Prozesse benutzen mehrere CPUs, aber nur einen gemeinsamen Speicherbereich.
  • Parallel Processing: Nebenläufige Prozesse benutzen mehrere CPUs und Speicher. Sie kommunizieren über ein schnelles internes Netz (Bus).
  • Distributed Processing: Nebenläufige Prozesse benutzen mehrere CPUs und Speicher. Sie kommunizieren über ein schnelles externes Rechnernetz (LAN).

In UNIX werden z.B. parallele Prozesse durch den Systemcall "fork()" erzeugt und über "join()" mit dem Vaterprozess synchronisiert, um die Ergebnisrückgabe des Kind-Prozesses an den Vater an einer bestimmten Stelle geschehen zu lassen.

Eine andere Möglichkeit zur Realisierung nebenläufiger Prozesse sind die "cobegin_coend"-Programmkonstrukte:

cobegin 
  Prozess 1; 
  Prozess 2; 
  ... 
  Prozess n; 
coend

6.2. Prozesskontrollblöcke

Prozesskontrollblöcke sind Datenstrukturen im Kernel, die dem Betriebssystem helfen, Prozesse zu verwalten. Hier wird für jeden Prozess PID, Priorität, Programmzähler, Register, Stack-Pointer, Zustandsdaten usw. gespeichert.

6.3. Prozessverwaltungsmodell nach dem Task-Thread-Prinzip

Tasks sind die kleinste Verwaltungseinheit zur Betriebsmittelvergabe (z.B. Stack und Memory). Sie sind heavy-weight, wenn sie mehrere Threads enthalten. Sie sind medium-weight, wenn sie mehrere Threads enthalten, die einen eigenen Stack, aber auch einen gemeinsamen Adressraum besitzen. Sie sind lightweight, wenn sie nur einen Thread enthalten.

Threads sind die Basiseinheit des Scheduling, denn sie sind es, die die Berechnungen eines Prozesses durchführen, die also die CPU beanspruchen. Wenn der sie enthaltende Task nicht medium-weight ist, verfügen Threads über einen eigenen Speicherbereich und einen eigenen Stack, d.h., jeder Thread kann parallel innerhalb eines Tasks ablaufen.

MACH ist z.B. ein Betriebssystem, welches mit dem oben beschriebenen Task-Thread-Verwaltungsmodell arbeitet. Seine Tasks sind medium-weight, die enthaltenden Threads teilen sich also einen gemeinsamen Adressraum, hier Segmente genannt, die dynamisch vom Betriebssystem anzufordern sind. Die Prozesskontrollblöcke sind auf Heterogenität eingestellt, d.h., sie können sich der Architektur des Rechners anpassen, auf dem sie gerade laufen. Daher muss der Benutzer mittels Process Capabilities zuerst einmal einen Host-Descriptor anfordern, der eine Maschinen-Architektur-Beschreibung enthält. Über diesen gelangt er zu einem Prozess-Descriptor, der die Capabilities auf einen Exception Handler, Segment-Handler und Thread-Handler vergibt, die einen Task verwaltbar machen. Auch gibt es bei MACH keine einfachen Systemcalls mehr, sondern es wird zur IPC ein Kernel-Server benutzt, dessen Nachrichtensystem zwar umständlicher ist, der damit aber genauso behandelt wird wie jeder andere Dienst in einem verteilten Betriebssystem.

6.4. Scheduling

Der Scheduler sorgt dafür, dass jeder lokale Thread gemäss seiner Auslastung CPU-Zeit zugewiesen bekommt. Dabei kann er zyklisch vorgehen, prioritätsgesteuert sein oder Strategien anwenden wie "shortest first" oder "first come, first serve".

6.4.1. Prozess-Status

In Betriebssystemen kann ein Prozess folgende Status innehaben, die mittels des Dispatchers gewechselt werden:

  • Running: Prozess ist im Besitz der CPU.
  • Ready: Alle Betriebsmittel bis auf CPU vorhanden.
  • Wait: Prozess inaktiv/beendet.
  • Lock: Prozess zur Synchronisation mit anderem Prozess blockiert.

6.4.2. Globales Scheduling und Lastenausgleichsstrategien

In verteilten Betriebssystemen genügt das normale Scheduling nicht, da sich dieses auf nur eine CPU und einen Rechner mit lokalen Tasks beschränkt. Was nötig ist, ist ein globales Scheduling (was streng genommen gar kein Scheduling mehr ist). Damit ein solcher globaler Scheduler erkennen kann, von welchem Prozessor er welchen Task ausführen lässt, ist es sinnvoll, dass er erfährt, wie ausgelastet die einzelnen CPUs im Netz sind. Das Dilemma dabei ist immer, dass man eigentlich erst nach dem Prozessablauf abschätzen kann, wie gross sein Betriebsmittelbedarf ist. Sehen wir uns dazu einige Lastenausgleichsstrategien an:

  • Lastenabstossungsstrategie (auch "Börsen"-Algorithmus genannt, weil hier das beste "Maklerangebot" gesucht wird, nach dem sich der "Verkäufer" dynamisch-lokal entscheidet):
    LOOP DO
       Lastenmessung in Delta-t
       IF Überlast THEN an alle Knoten: Wer nimmt meinen Prozess?
    
  • Lastenanziehungsstrategie:
    LOOP DO
       Lastenmessung in Delta-t
       IF Unterlast THEN an alle Knoten: Wer hat einen Prozess für mich?
    
  • Token Passing: Der Rechner, der das Token hat, kann sich broadcast Lastinformationen einholen und darf dann evtl. Prozesse verlagern.
  • Wurm-Programmierung: Das Wurmprogramm kann sich auf freien Rechnern fortpflanzen und dann dort eine Migrations-Arbeitsumgebung schaffen, die mit all seinen Segmenten auf den anderen Rechnern kommunizieren kann.

Die Lastausgleichsstrategien eignen sich auch für ein Migrieren von Tasks, d.h. für ein Verlagern von Prozessen noch während der Laufzeit, was v.a. bei lange dauernden Prozessen sinnvoll sein kann. Problematisch dabei ist aber, dass bei jeder Migration der komplette Adressraum des Prozesses mitkopiert werden muss (bei Teilmigration ist auch eine "Copy on Reference"-Aufforderungsstrategie möglich).

6.4.3. IPC nach Prozessmigration

Wie soll die Inter-Process Communication danach weitergeführt werden?

  • Weiterleitungsnachrichtenfluss: Statthalter könnten im alten Knoten bleiben, die alle ankommenden Nachrichten an den neuen Knoten weiterleiten.
  • Vorab-Informations-Nachrichtenfluss: Vor der Migration werden alle Partnerprozesse über den neuen Knoten informiert.
  • Verlust- und Recovery-Nachrichtenfluss: Nach der Migration werden alle Partnerprozesse über den neuen Knoten informiert - dadurch gehen alle Nachrichten dazwischen verloren, die jedoch u.U. rekonstruierbar sind.

6.5. Zu merken

Verteilte Betriebssysteme sollten Prozesskontrollblöcke besitzen, die für verschiedene Rechnerarchitekturen benutzbar sind. Das Task-Thread-Prozess-Verwaltungsmodell erlaubt die parallele Verarbeitung von Prozessen innerhalb einer Verwaltungseinheit. Dies erhöht bei heavy-weight-Tasks die Geschwindigkeit, aber auch den Verwaltungsaufwand - light-weight-Tasks scheinen uns daher die angemesseneren zu sein. Auch was das Scheduling angeht, heisst Einfachheit die Devise: Lastenausgleichsstrategien über globale Scheduler und Migration von Prozessen kosten mehr, als dass sie nutzen - auf sie sollte verzichtet werden.

7. Dateiverwaltung

7.1. Schichtsysteme

Herkömmliche Dateiverwaltungssysteme werden geschichtet aufgebaut, wobei jede Schicht bestimmte Dienste für die darüberliegende Schicht erledigt. Auch oder v.a. bei verteilten Betriebssystemen ist das Schichtsystem einzuhalten, z.B. in der Form:

Disk-Service -> File-Service -> Directory-Service -> Transaktionsservice

Anders als bei herkömmlichen Betriebssystemen muss in einem verteilten Betriebssystem nicht jeder Rechner alle Schichten integriert haben. Es genügt, wenn ein Rechner z.B. nur eine Schicht (nur einen Dienst) zur Verfügung stellt, und die restlichen Schichten sich ganz woanders befinden. Bis zu einem gewissen Grad ist dieses Prinzip bereit in UNIX zu finden, wo es Diskless-Workstations gibt, die auf Datei-Server angewiesen sind (nur bis zu einem gewissen Grad deshalb, weil die hier verwendeten Datei-Transfersysteme wie FTAM und FTP nicht transparent arbeiten).

7.2. Organisation von verteilten Dateisystemen

  • Zentraler Datei-Server, der die komplette Dateiverwaltung übernimmt.
  • Replizierter Datei-Server, der zwar skalierbar ist, aber Update-Problemen unterliegt, und wo der jeweils richtige Server für den Client schwerer zu finden ist.
  • Vollständig verteiltes Dateisystem: Alle Rechner können Datei-Server sein für ihr lokales Umfeld, sind also mit einem eigenen Dateisystem ausgestattet.

7.3. Dateizugriffsdauer

Ein Problem bei verteilten Dateisystemen, die ja auch die Kernel-Dienste als ausführbare Prozesse anbieten sollen, ist der erhöhte Bedarf an Zeit pro Dateizugriff, die sich zusammensetzt aus:

  • Plattenzugriffszeit + E/A-Kanalübertragungsdauer (diese Zeit kann fast auf null reduziert werden, wenn Cache-Techniken eingesetzt werden).
  • DÜ übers Netz (kommt bei entfernten Zugriff hinzu).
  • CPU-Zeit zur Bearbeitung der Informationen.

7.4. Dateinamensfindung

Das Suchen von Dateinamen im Netz kann der Client übernehmen, doch sollte dazu besser ein Datei-Server verwendet werden. In der Regel wird dieser Pfadnamen über rekursive Lookup-Algorithmen zu lokalisieren versuchen (z.B. Lookup von "/a/b/C/prg1"). Dies erscheint v.a. im Zusammenhang mit den oben vorgestellten verketteten Datei-Servern sinnvoll, die jeweils ihren Kontext durchsuchen können. Verbesserungen sind mittels Caching möglich. Auch ein NFS-ähnliches Mounting zur Schaffung eines globalen Dateibaums erleichtert das Lookup, da es sich auf die gemounteten Teilbäume beschränken kann.

Zur Verdeutlichung: Mittels NFS will Rechner A über das Verzeichnis "A:/usr1/shared" den Directory-Baum "B:/usr2/local" des Rechners B mounten. Herauskommt: "A:/usr1/local", wobei der ursprüngliche Teilbaum erst nach einem Remount wieder zugreifbar ist.

7.5. Zugriffssemantik

Welche Bedeutung hat ein (ändernder) Dateizugriff eines Prozesses für andere Prozesse?

  • UNIX-Semantik: Wenn hier jemand eine Datei beschreibt, dann bekommt das jeder andere Prozess bei einem Read unmittelbar mit. Der Dateiserver kann stateless und verbindungsunabhängig sein. Dadurch ist das Netz durch seinen Absturz nicht sehr gefährdet. Allerdings muss sichergestellt sein, dass Prozesse, die er anbietet, idempotent sind.
  • Session-Semantik: Wenn hier jemand eine Datei beschreibt, bekommen dies nur die lokalen Prozesse unmittelbar mit, weil die entfernten Prozesse mit Duplikaten arbeiten. Der Dateiserver kann stateless oder stateful sein.
  • Immutable Semantik: Wenn hier jemand eine Datei beschreiben will, so muss er zuerst ein Duplikat davon erzeugen. Der Dateiserver dürfte stateless sein.
  • Transaction-Semantik: Wenn hier jemand eine Datei beschreibt, hat er sie zuvor mit einer Lock-Option geöffnet. Der Dateiserver ist dann meist stateful und verbindungsorientiert, d.h., er merkt sich für jeden Client die Position des Schreiblesekopfs u.ä. Ein Absturz kann das Netz zusammenbrechen lassen. Aber auch ein stateless Datei-Server ist denkbar.

7.6. Caching

Hier wird das Lokalitätsprinzip ausgenutzt, also die Tatsache, dass ein Prozess meistens Dateien beansprucht, die sich in unmittelbarer Nähe zueinander befinden. Daher ist es sinnvoll bei entfernten Zugriffen nicht nur den einen Dienst, sondern gleich ganze Blöcke oder Seiten in den lokalen Speicher des entfernten Rechners (oder des eigenen) zu kopieren.

Wichtig sind dabei Validierungsstrategien bzw. Update-Strategien, die am besten vom Dateiserver durchgeführt werden, um sicherzustellen, dass der Cache-Inhalt mit dem Platteninhalt übereinstimmt. Hierzu bieten sich an:

  • write through: Jedes Cache-Beschreiben bewirkt Plattenbeschreiben.
  • delay write: Schreiben vom Cache auf Platte z.B. alle 30 Sekunden.
  • write-on-close: Schreiben vom Cache auf Platte wenn der Dateizugriff beendet wird.

7.7. Zu merken

Auf das Schichtprinzip kann bei verteilten Betriebssystemen nicht verzichtet werden. Vollständig verteilte Dateiserver sind zentralen Dateiservern vorzuziehen. Zur Dateinamensfindung sollten fremde Directories in den eigenen Directory-Baum montierbar sein, die Suche übernehmen die Datei-Server über ein rekursives Lockup der Pfade. Für den Dateizugriff sind stateless Datei-Server vorzuziehen, die nach der Transaction-Semantik arbeiten. Und auf Caching - v.a. bei den entfernten Server-Rechnern - sollte wohl auch nicht verzichtet werden.

8. Zusammenfassung

In den obigen Kapiteln wurde beschrieben, auf welche verschieden Weisen sich verteilte Betriebssysteme realisieren lassen.

8.1. Checkliste für das optimale verteilte Betriebssystem

Im Anschluss zu jedem Kapitel wurde dabei die Favorisierung bestimmter Eigenschaften vorgenommen, die wir hier nun in Form einer Checkliste für ein optimales verteiltes Betriebssystem auflisten wollen:

  • Client/Server-Interaktionsmuster
  • Client/Server-Kooperationsorganisation
  • Broadcast-Medium
  • Load Sharing-Server
  • Synchrone Kommunikation
  • auftragsorientiertes Kommunikationsmodell
  • Primitive-Austausch
  • verkettete Name-Server
  • Weitergabe-Methode zur Namensauflösung
  • abhörsicheres Subnet
  • 2-Wege-Eingangsautorisierung
  • Zugriffs-Capabilities
  • asymmetrische Codierung (öffentliche Schlüssel)
  • Autorisierungsserver mit Name-Server kombiniert
  • einmalige Nachrichten zur Entschlüsselungsprobe
  • von der Heterogenität adaptive Prozesskontrollblöcke
  • Task-Thread-Prinzip mit Lightweight-Tasks
  • globales Scheduling ohne Lastenausgleich und Migrationsstrategien
  • Schichtkonzept
  • vollständig verteilte Dateiserver
  • montierbare Directories
  • stateless Dateiserver
  • Transaction-Semantik
  • Caching beim entfernten Server

9. Ein Beispiel - AMOEBA

AMOEBA ist ein Forschungssystem der Universität Amsterdam, entwickelt u.a. von Andrew S. Tanenbaum. Es handelt sich hierbei um ein verteiltes Betriebssystem der Art Kernverbundsystem, d.h., dass nur der Kern des Betriebssystem SIDOS (Single Disk Operating System) auf allen Knoten läuft. Die an das LAN angeschlossenen Workstations sind alleine nicht lauffähig, sie beherrschen nur noch die Inter-Process Communication- (IPC) und die E/A-Kanäle. Sie finden im Netz einen Prozessorpool und diverse Server-Rechner, die alle sonstigen Betriebssystemleistungen stellen können, z.B. die Datei- und Speicherverwaltung.

An besonderen Servern gibt es:

  • Bullet-Server: Ein spezieller Datei-Server, der keine Dateiänderungen erlaubt und daher sehr schnell arbeitet, weil z.B. die konkurrierende Zugriffssteuerung weg fällt.
  • Boot-Server: Ein Überwachungsserver, der dafür sorgt, dass ein abgestürzter Server wieder hochgefahren wird.