Verteilte Betriebssysteme
von Daniel Schwamm (02-03/1994)
Aus "Heimat des Dilettantismus"
http://www.henrys.de/daniel/index.php?cmd=texte_verteilte-betriebssysteme.htm
nach Dr. Jürgen Schneider von IBM (Sommersemester 1993)
Inhaltsverzeichnis
1. Einführung
-> SISD, MIMD, verteiltes Betriebssystem, UNIX, FTP
2. Ein Beispiel - AMOEBA
-> Bullet-Server, Boot-Server
3. Interaktionsmuster und Prozeßorganisation
-> Piplining, Peer-to-Peer, C/S, Heartbeat, Probe/Echo, Token Passing
-> Work/Load Sharing, Server-Replikation, C/L-Kooperation
4. Kommunikationsmodelle
-> Mitteilung (No-Wait/Rendezvous), Auftrag (Remote), Transaktion
-> Maybe, At Least/Most Once, Exactly Once
5. Namenverwaltung
-> Identifikation, Indirektion, Abstraktion
-> Chaining, Verweisen, Weitergabe, Multicast
-> X.500, V-Kernel
6. Schutzmechanismen und Sicherheit
-> Ein-/Zwei-Wege-Autorisierung, (a)symmetrische Kryptologie,
Capabilities
7. Prozeßorganisation
-> Nebenläufigkeit, Task-Thread-Prinzip, MACH, Scheduling,
Lastenausgleich, Migration, Statthalter
8. Dateiverwaltung
-> Schichten, Zugriffssemantik, Caching
9. Zusammenfassung
1. Einführung
Am Anfang der Informationstechnologie gab es nur den von Neumann-Rechner mit
seiner SISD-Architektur: Instruktionen und Daten werden hier aus demselben
Speicher geladen, von einer Kontrolleinheit dekodiert und von nur einem Prozessor
verarbeitet. Später wurde die Rechnerarchitektur MIMD entwickelt, bei der
mehrere Prozessoren paralle arbeiten, die jeweils einen eigenen Daten- und
Instruktionsstrom besitzen. Je nachdem, ob die Prozessoren über einen
gemeinsamen Speicher kommunizieren bzw. jeder einen seperaten unterhält,
spricht man von Multiprozessorsysteme (z.B. die Cray-Rechner) bzw.
Multicomputersysteme, zu dem im weiteren Sinne auch die hermömmlichen
Rechnernetze gehören.
Rechnernetze sind stark im Wachstum begriffen. Die HW der Computer, Knoten
und Übertragungsmedien verfügt über immer mehr
Leistungskapazität bei gleichzeitig fallenden Preisen. Die Vernetzung
der Welt ist daher ein Prozeß, der sich in den kommenden Jahren sicher
noch explosionsartig weiter entwickeln wird. Der Höhepunkt der
bisherigen Rechnernetztechnik stellen die sogenannten verteilten
Betriebssysteme dar, die von ihrerer 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, von einander
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
soviel an Leistung, wie der abgestürtzte Rechner durch seine CPU
dazugegeben 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 ausschließen und Verteilungstransparenz ermöglichen.
Verteilungstransparenz ist die höchste in einem Netzwerk erreichbare
Transparenzstufe. Sie sagt aus, daß ein Knotenprozeß nicht explizit
angeben muß, wo sich ein anderer Prozeß, mit dem er kommunizieren
muß, innerhalb des verteilten Betriebssystems befindet - dieses Wissen
wird quasi implizit vom verteilten Betriebssystem gestellt.
Verteilungstransparenz umfaßt 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 muß jedoch jedem Prozeß 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, daß nicht-verteilte
Betriebssysteme über keine Verteilungstransparenz verfügen, auch
wenn sie diese Problematik durch graduell verschiedenen Tools bzw. Dienste
zu umgehen suchen.
Sehen wir uns das nicht-verteilte Betriebssystem UNIX an. Es versucht
über folgende Methoden eine Art Verteilungstransparenz zu erreichen:
* Dateisystem: das UNIX-Dateissystem erlaubt das Kopieren von Dateien
innerhalb des lokalen Rechnernetzes unter Angabe des Pfadnamens (keine
Ortstransparenz gegeben).
* Network-Disk-Server: ein Diskettenserver, der es mehreren (diskeless)
Workstations ermöglicht, über ein entferntes Diskettenbetriebssystem
Daten auszutauschen. Auch hier muß der Pfadname vollständig
angegeben werden.
* NFS: ein verteiltes Dienstprogramm (in UNIX integriert), welches die
Montierung 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 Montierung kann fast von Lokations- und Zugriffstransparenz gesprochen
werden, aber eben nur fast: die Pfadnamen des eigenen Directory-Baums
müssen weiterhin angebenen werden. Schwerwiegender ist aber, daß
vor dem Montieren keine Ortstransparenz vorliegt, da der Benutzer wissen
muß, wo sich das zu montierende Verzeichnis finden läßt.
Auch unterstützt NFS keine Transaktionen, da es mit zustandslosen
Servern (svw.) arbeitet. Unter Verwendung der UDP- bzw. TCP-Protokolle
gestattet es aber immerhin RPCs von pointerlosen, idempotente Funktionen,
die über Timeout- und Duplikations-Techniken sogar zuverlässig
arbeiten können.
AMOEBA ist ein Forschungssystem der Universität Amsterdam, entwickelt
u.a. von A. Tanenbaum. Es handelt sich hierbei um ein verteiltes Betriebssystem
der Art Kernverbundsystem, d.h., daß 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 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 Filseserver, der keine Dateiänderungen
erlaubt und daher sehr schnell arbeitet, weil z.B. die konkurrierende
Zugriffssteuerung wegfällt.
* Boot-Server, ein Überwachungsserver, der dafür sorgt, daß
ein abgestürtzter Sever wieder hochgefahren wird.
3. Interaktionsmuster und Prozeßorganisation
Interaktionsmuster geben an, wie sich Prozessoren koordinieren können,
um gemeinsam ein Problem bearbeiten zu können. Sechs verschiedene Methoden
werden wir uns dazu ansehen.
(1) Pipelining: bei diesem Interaktionsmuster empfängt ein Prozeß
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
hinsenden, so muß er dazu eine neue Pipline 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
Dienstleistungsforderer 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 Basisprozeß) eine sogenannte Probe-Nachricht
an seine Kinder weiter, die sie dann weiter an ihre Kinder leiten usw., bis sie
schließlich das Baumende/den Zielprozeß 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, daß stets nur der Nachrichten versenden darf, der im
Besitz des Tokens ist. Jeder kann das Token nur für kurze Zeit halten und
muß es dann weitergeben, so daß kein Prozessor über längere
Zeit das ganze Kommunikationsmedium blockieren kann (es geht also "fair" zu!).
Unter Umständen ist es auch möglich, daß sich mehrere Token im
System befinden, so daß durchaus auch parallel Nachrichten versendet werden
können.
PROCESS Pi
LOOP DO
RECEIVE(token);
...
SEND(token);
END
Oben haben wir gesehen, über welche Interaktionsmuster Prozesse
Nachrichten austauschen können. In verteilten Betriebssystemen ist davon
auszugehen, daß sich die Prozesse nicht auf den gleichen Rechnern befinden,
daher müssen die Prozesse so organisiert werden, daß sie über ein
LAN (u.U. auch über ein WAN) hinweg miteinander kommunizieren können.
Insbesondere muß auch dafür gesorgt werden, daß alle Rechner
im LAN gleichmäßig ausgelastet werden. Man spricht hier von
Prozeßorganisation oder besser: Serverorganisation, weil den verteilten
Betriebssystemen fast immer das Client/Server-Interaktionsmuster zugrunde liegt.
Verschiedenen Methoden der Serverorganisation 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 Serverprozeß zugeordnet ist. Jeder Client braucht hier
also nur die Serveradresse zusammen mit der Portnummer ins LAN eizugeben und
schon bekommt er Zugriff auf einen bestimmten Dienstprozeß des
Serverrechners. Dies hat allerdings den schweren Nachteil, daß jeder
Serverprozeß 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 Porteingä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 weißt 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ößeren LANs ist es üblich,
daß mehrere Server-Rechner eingesetzt werden, die jeweils die gleichen
Dienste anbieten. Damit die Clients die Dienste von den am wenigsten
ausgelasteten Serverrechner ausgeführt bekommen, ist es nötig,
einen Server-Server zu betreiben, den sogenannten Poolmanager. Alle Requests
der Clients gehen also nicht an die Dienstserver, sondern an den Poolmanager,
der dann einen Server-Rechner bestimmt, der den gewünschten 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 Poolmanager, sondern gibt sie
broadcast ins Netz. Hier gibt es nun verschiedene Arten, wie mit dieser
Broadcast-Nachricht verfahren wird. Einmal ist es möglich, daß die
Clients sich damit untereinander abstimmen, wer welchen Server benutzen darf
(clientkontrollierte Auswahl). Besser ist es aber, die Server selbst bestimmen
zu lassen, wie sie auf den Broadcast-Request reagieren sollen
(serverkontrollierte Auswahl). Die Server kennen sich i.d.R. gegenseitig und
können dadurch den jeweiligen Auslastungsgrad ermitteln, so daß
sich stets der am wenigsten ausgelastete Server bei Client melden kann.
PROCESS Client
DO
BROADCAST(wer ist frei?);
RECEIVE(ack von bst. server);
SEND(request);
RECEIVE(reply);
END
Zu merken: Interaktionsmuster haben etwas damit zu tun, wie sich Prozesse
untereinander Nachrichten zusenden. Prozeßorganisation hat etwas damit
zu tun, wie dafür gesorgt werden kann, daß alle Rechner im Netz
gleichmäßig ausgelastet werden können.
4. 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. Desweiteren wurde gezeigt, wie sich die im Netz verteilten
Serverprozesse gegenseitig organisieren, so daß die einzelnen
Server-Rechner möglichst gleichmäßig ausgelastet sind.
In diesem Kapitel wenden wir uns der Nachrichtenart Primitive zu. Diese
dienen dazu, aus einem (Client-)Prozeß heraus einen anderen
(Server-)Prozeß zu erzeugen. Je nach Komplexität solcher
Primitive können die folgenden Kommunikationsmodelle unterschieden werden.
(1) mitteilungsorientierte 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: unquittiertes Emailing.
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 jeoch, daß der
Empfänger entweder über Puffer verfügt oder ein "Busy-Waiting"
durchführt. Evtl. kann auch im Netzwerk selbst ein Pufferrung 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 (außer evtl. zur
Flußkontrolle).
(2) auftragsorientierte Kommunikationsmodell: bei diesem Modell erhält
der Client nach Sendung des Primitives ein Resultat von dem dadurch erzeugten
Server-Prozeß zurück. Die auftragsorientierten Primitive sind also
duplexe Nachrichten. Ein Beispiel hierfür: Uhrzeit-Server.
Im asynchronem Betriebsmodus arbeitet der auftragsorientierte Sender nach
dem "Remote Service Invocation"-Prinzip. Hier kann der Client nach der
Dienstanforderung weiterarbeiten und muß nicht warten, bis der Server die
Antwort sendet (Nicht-Blockierung). Diese Technik wird allerdings in der Praxis
kaum realisiert.
Im synchronem Betriebsmodus arbeitet der Sender nach dem
"Remote Procedure Call"-Prinzip. Hier arbeiten Primitive genauso wie
Unterprogramme. Während das Unterprogramm (der Serverprozeß)
ausgeführt wird, blockiert das Hauptprogramm (der Clientprozeß)
solange. Dies ist die meist benutzte Technik bei verteilten Betriebssystemen,
wobei das erklärte Ziel völlige Transparenz ist, d.h. daß
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-Prozeß erhalten, wenn sie zuvor vollständig
abgearbeitet worden sind. Dadurch wird effektiv ausgeschlossen, daß 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: sie sind Atomic (arbeiten nach dem
Alles-oder-Nichts-Prinzip), Consistency (gehen von einem konsistenten Zustand
in einen anderen über), Isolationed (zeigen nur bei Erfolg Auswirkungen)
und Durability (ihr Erfolg geht nicht verloren).
Die oben aufgeführten Kommunikationsmodelle sind erheblich variierbar,
wodurch sie optimal auf das jeweilige Subnet oder die zugrundeliegende
Rechnerkonfigurastionen angepaßt werden können. 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-blokierenden Knoten und also asynchronem Betrieb nötig.
* atomic/zuverlässig/unzuverlässig, wobei folgende Fehlerklassen
möglich sind:
- "maybe" : ein Packet kommt vielleicht nie am Ziel an.
- "at least once": mindestens ein (Duplikat-)Packet erreicht Ziel.
- "at most once": höchstens ein (Duplikat-)Packet erreicht Ziel.
- "exactly once": idealisiertes "at most once".
* direkt oder indirekt adressierend, d.h. der Client spricht einen
Serverdienst direkt oder indirekt über einen Nameserver an.
* blockierend/unblockierend (i.d.R. identisch mit synchron/asynchron), d.h.
der Client kann evtl. weiterarbeiten, während der Server den Dienst
erfüllt.
Als Protokolle kommen üblicherweise Fensterprotokolle in Frage (v.a.
beim asynchronen Betrieb), die durch Wahl ihrer Fenstergröße sehr
anpassungsfähig sind. Bei Fenstergröße von eins hat man z.B.
ein einfaches Stop-and-Wait-Übertragungsprotokoll, bei großer
Fensterwahl dagegen ein recht komplexes.
Zu merken: Kommunikationsmodelle haben etwas mit 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 Betriebessysteme am ehesten geeignete.
5. Namensverwaltung
In einem Rechnernetz haben folgende Objekte Namen: Rechner (Knoten),
Prozesse und Benutzer. Die Aufgaben der Namensgebung sind:
* 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.
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 Nameserver über seine Kontextinformationen
herausfinden muß. Das hat den großen Vorteil, daß Objekte
mit reinen Namen migrieren können ohne ihren Namen neu definieren zu
müssen.
* flach/hierachisch/routingorientiert.
* benutzerfreundlich/maschinengerecht, erstere sind i.d.R. hierachisch,
zweitere flach/routingorientiert. 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 ganzem/teilhaftem Pfadnamen versehen.
* direkt/indirekt, wobei letzteres bedeutet, über Mailbox, Ports oder
Links bestimmte Prozesse anzusprechen.
Mögliche Erscheinungsformen von global eindeutigen Namen sind:
* 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 zeitstransparent. Z.B. eine Prozeß-ID.
* Adressen, die zwar nicht ortstransparent sind, dafür aber meistens
zeitstransparent. Z.B. Ethernetadresse.
Die meisten Name werden letztlich auf Adressen abgebildet (über eine
sogenannte Abbildungsfunktion). Dabei wird kontextabhängig-anayltisch
vorgegangen, d.h. der Name wird aufgespalten, wobei jeder Teil (jedes Attribut)
einen anderen Rechnernetz-Kontext umfaßt, abhängig davon, ob ein
hierarchischer, routingorientierter oder sonstiger nicht-flacher Adressenaufbau
vorliegt.
Nameserver sollen helfen, in verteilten Betriebssystemen globale Kontexte
aufzubauen. Neben der Namensverwaltung führen sie üblicherweise auch
die Authentifikation der Clients durch. Sie werden folgendermaßen
organisiert:
* zentraler Nameserver: ein Server verwaltet alle Namen im Netz,
verfügt also über den (idealen) globalen Kontext.
* verteilter Nameserver mit ortsabhängigen Namen: jeder Client ist auch
Nameserver, der bei Broadcast-Calls reagiert, wenn er den gesuchten Namen im
eigenen Kontext führt. Der Pfadname muß jedoch mitangegeben werden,
d.h. ortstransparente Namen sind nicht möglich.
* voll verteilter Nameserver: jeder Client ist auch Nameserver, der jeden
beliebigen Namen auflösen kann. Ortstransparenz ist gegeben.
* verkettete Nameserver: in großen Netzen empfiehlt sich diese
Nameserver-Organisation. Jeder Nameserver verwaltet hier nur den Kontext von
Namen, die er selbst generiert hat. Findet er bei einer Anfrage den gesuchten
Namen nicht, werden andere Nameserver kontaktiert. Die Namensauflösung bei
verketteten Nameservern kann auf vier Methoden geschehen:
- Chaining-Methode: Ein Name Agent-Prozeß des Client-Rechners fragt
den Nameserver seines Kontextes nach einem Namen. Findet dieser den Namen
nicht, so fragt er den nächsthöheren Kontext-Nameserver. Findet
dieser den Namen, so meldet er ihn dem ersten Namesrerver 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 Nameserver.
- Verweisungsmethode (Referential Method): Bei dieser Methode erfährt
der Name Agent bei Suchmißerfolg eines Nameservers von dienem jeweils die
Adresse des nächsthöheren Kontext-Nameservers, den er dann selbst
kontakieren muß.
- Weitergabe-Methode: Hier hangelt sich die Suche ähnlich zu der
Chaining-Methode immer höher in den Baum, bis der Name bei einem
Kontext-Nameserver gefunden wird. Diesmal wird allerdings danach nicht mehr der
Baum zurückgelaufen, sondern die bekannte physische Adresse des Name Agent
direkt kontaktiert.
- Broadcast-Methode: jeder Client bekommt den gesuchten Namen zugesendet und
der richtige Client andwortet. Diese Methode wird z.B. im ARPA Internet durch
das ARP-Protokoll realisiert: man fragt nach "Susanne" und erhält
"129.55.210.111" zurück.
- Muticastcast-Methode: nicht jeder Client, sondern nur jeder
Kontext-Nameserver erfährt den gesuchten Namen und sieht nach, ob er ihn
verwaltet. Wenn ja, meldet er sich beim Client.
Als Beispiel für einen Nameserver kann die X.500-Norm der CCITT
angeführt werden. Dieser globale Directory-Dienst arbeitet mit einer
verketteten Nameserver-Architektur, benutzt daher auch hierarchische Namen,
die kontextuell folgendermaßen 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 kürzeren Nameserver-Blockierung sicher die
Weitergabe-Methode die bessere wäre.
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).
Zu merken: Namen werden in verteilten Betriebbssystemen i.d.R. durch
Nameserver verwaltet. Als die Geeignetsten erscheinen uns dabei verkettete
Nameserver, die zur Namensauflösung die Weitergabe-Methode praktizieren.
6. Schutzmechanismen und Sicherheit
In einem verteilten Betriebsystem sind die Benutzer, die Betriebsmittel und
die Daten zu schützen. Alternativ kann entschieden werden, ob die
Schutzmechanismen im Betriebsystemkern verankert werden oder ob sie dem zu
schützenden Objekt beigefügt werden. Im ersten Fall muß von
einem abhörsicheren Betriebssystem ausgegangen werden und im zweiten Fall
von einem abhörsicherem Kommunikationssystem. Der zweite Fall scheint
uns für ein verteiltes Betriebssystem bessere zu sein, da hier die
Systemcalls zum großen Teil über Remote Procedure Calls simuliert
werden, die über das Subnet abewickelt werden. Solche RPCs laufen
über Clinet/Server-Stubs ab, die über eine Boradcastnachricht bzw.
einen Directory-Service das Linken zwischen den Ports übernehmen und z.T.
auch noch eine einfache Datenrepräsentation über Kodierregeln
erlauben.
Es gibt viele Wege, ein verteiltes Betriebssystem sicher zu gestalten und
vor Mißbrauch zu schützen. Einige davon seien im Folgenden
vorgestellt.
(1) Ein-Wege-Autorisierung: der Benutzer muß sich gegenüber als
autorisierter Benutzer identifizieren. Hierfür eignen sich die klassischen
Paßwortverfahren.
(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, daß "Login-Masken"-Programme den Benutzer täuschen
können, die nur dazu dienen, die Paßwörter der Benutzer
abzufangen. Auch hierfür eignen sich die Paßwortverfahren.
(3) Autorisierungsprozesse zu Beginn einer Computersitzung können nie
ganz sicherstellen, daß nicht doch ein Unbefugter ins Netz hineinkommt.
Sei es durch Zufall oder weil er ein Paßwort geklaut oder erraten hat.
Wirklich sensible Daten werden daher häufig noch über kryptologische
Verfahren geschützt. Grob unterschieden werden hier zwei Arten:
* symmetrische Verfahren: Kodierung und Dekodierung erfolgen über nur
einen geheimen Schlüssel.
* asymmetische Verfahren: Kodierung und Dekodierung erfogen über
jeweils verschiedene Schlüssel.
(4) Sichere verteilte Betriebsysteme müssen sich vergewissern,
daß ein Client, der einen Dienst anfordert, dazu überhaupt
berechtigt ist. Daher muß sich der Client dazu zuvor einer
Authentifizierungsprozedur unterziehen. Hier existieren zwei Strategien:
* der Client (Subjekt) weiß nicht welche Rechte er auf welche Dienste
(Objekte) hat, der Dienstserver kann dies jedoch über Zugriffsmatritzen
feststellen unter dadurch u.U. eine Verbindung unterdrücken. Zuvor muß
sich der Client bei einem Nameserver 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
über's Ohr hauen.
* der Client weiß welche Rechte er auf welche Dienste hat, weil er
für sie bestimmte Capabilities besitzt. Solche Capabilities sind im Prinzip
alternativ implementierte Zugriffsmatrizen. Will er einen Dienst bei einem Server
anzufordern, so authentifiziert er sich zuerst beim Nameserver und sendet diesem
seine Capability zu. Nur wenn sie korrekt ist, rückt der Nameserver mit der
Dienstserveradresse und der Portnummer für den gewünschten Dienst
heraus.
Auch wenn es nötig ist, daß die Capabilities
fälschungssicher sein müssen, so empfiehlt sich die
Capapility-Methode doch eher als die Zugriffsmatrix-Methode, um einen Client
dazu zu Autorisieren, einen bestimmten Dienst nutzen zu dürfen.
Wir wollen uns nun einen einfachen Algorithmus ansehen, der dafür
sorgt, daß ein Server sicher sein kann, daß der Client auch genau
der ist, für den er sich ausgibt (was natürlich nicht heißt,
daß 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 kodiert 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. Außerdem muß hier jeder Server sämtliche
Schlüssel führen.
Um Replies zu verhindern, kann man einmalige Nachrichten (z.B. Uhrzeiten)
versenden, die ein Unautorisierter nicht kodieren 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 kodiert die einmalige Nachricht und sendet sie zurück.
4. Server prüft, ob die einmalige Nachricht richtig kodiert wurde.
Problematisch bleibt nach wie vor, daß jeder Server sämtliche
Schlüssel der Clients kennen muß. Hier kann man sich mit der
Einführung einer dritten Instanz helfen: eines Autorisierungsservers.
1. Client sendet "Ich bin C" an Server.
2. Server sendet einmalige Nachricht an Client.
3. Client kodiert einmalige Nachricht und sendet sie zum Server.
4. Der Server kodiert einmalige Nachricht mit eigenem Schlüssel,
sendet sie zum Autorisierungsserver.
5. Der Aurorisierungsserver entschlüsselt die einmalige Nachricht
zweimal, kodiert sie dann mit den Schlüssel des Servers und
sendet sie diesem zu.
6. Der Server entkodiert einmalige Nachricht und überprüft sie.
Bisher haben wir nur sysmmetrische Verfahren betrachtet. Der letzte
Algorithmus läßt 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 kodiert die einmalige Nachricht mit geheimen Schlüssel
und sendet sie zum Server zurück.
4. Server fordert vom Autorisierungsserver den öffentlichen
Schl;üssel von C an und entkodiert und prüft damit
geheime Nachricht.
Als Beispiel für Public Key-Verfahren läßt sich RSA nennen.
Hier ist die Idee, daß öffentlicher und privater Schlüssel
große Primzahlen sind, die miteinander dupliziert den Schlüssel
zur Entkodierung darstellen. Da es nun aber sehr schwer ist, eine solche
Multiplikation wieder aufzubrechen, selbst wenn ein Schlüssel und der
Programmcode bekannt sind (!), kann einer der Schlüssel ohne Gefahren
öffentlich verfügbar sein.
Zu merken: um verteilte Betriebssysteme sicher zu machen, muß 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 sich bei Nameservern bestätigen lassen, die sie dann mit
den Dienstservern verbinden. Um sicher zu gehen, daß Clients die sind,
für die sie sich ausgeben, empfiehlt sich die geheime Verschlüsselung
einmaliger Nachrichten, zu deren Überprüfung sich der Nameserver dann
jeweils beim Autorisierungsserver den öffentlichen Schüssel besorgen
kann.
7. Prozeßverwaltung
(1) Prozeßablauf: Prozesse laufen in Rechnern sequentielle 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 Vaterprozeß synchronisiert, um die
Ergebnisrückgabe des Child an den Vater an einer bestimmten Stelle
geschehen zu lassen.
Eine andere Möglichkeit zur Realisierung nebenläufiger Prozesse
sind die cobegin-Programmkonstrukte: cobegin Prozeß 1; Prozeß 2;
... Prozeß n; coend
(2) Prozeßkontrollblöcke: das sind Datenstrukturen im Kernel, die
dem Betriebssystem helfen, Prozesse zu verwalten. Hier werden pro Prozeß
die PID, Priorität, Programmzähler, Register, Stackpointer,
Zustandsdaten usw. gespeichert.
(3) Prozeßverwaltungsmodell: das Task-Thread-Prinzip.
* Tasks sind die kleineste Verwaltungseinheit zur Betriebsmittelvergabe
(z.B. Stack und Memory). Sie sind heavyweight, wenn sie mehrere Threads
enthalten. Sie sind mediumweight, wenn sie mehrere Threads enthalten, die einen
eigenen Stack, aber einen gemeinsamen Adreßraum besitzen. Sie sind
leightweight, wenn sie nur einen Thread enthalten.
* Threads sind die Basiseinheit des Schedulings, denn sie sind es, die die
Berechnungen eines Prozesses durchführen, die also die CPU beanspruchen.
Wenn der sie enthaltende Task nicht mediumweight 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 mediumweight,
die enthaltenden Threads teilen sich also einen gemeinsamen Adreßraum,
hier Segmente genannt, die dynamisch vom Betriebssystem anzufordern sind.
Die Prozeßkontrollblöcke sind auf Heterogenität eingestellt,
d.h. sie können sich der Architektur des Rechners anpassen, auf dem
sie gerade laufen. Daher muß der Benutzer mittels Process Capabilities
zuerst einmal einen Host-Deskriptor anfordern, der einen
Maschinen-Architektur-Beschreibung enthält. Über diesen gelangt
er zu einem Prozeßdeskriptor, 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
Betriebsystem.
(4) Scheduling: der Scheduler sorgt dafür, daß jeder lokale
Thread lastengleichmäßig CPU-Zeit zugesteuert bekommt. Dabei kann er
zyklisch vorgehen, prioritätsgesteuert oder Strategien anwenden wie
"shortest first" oder "first come, first serve". In Betriebsystemen kann ein
Prozeß folgende Stati inne haben, die mittels des Dispatchers gewechsel
werden:
* Running: Prozeß ist im Besitz der CPU.
* Ready: alle Betriebsmittel bis auf CPU vorhanden.
* Wait: Prozeß inaktiv/beendet.
* Lock: Prozeß zur Synchronisation mit anderem Prozeß
blockiert.
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 strenggenommen gar kein
Scheduling mehr ist). Damit ein solcher globaler Scheduler erkennen kann, von
welchem Prozessor er welchen Task ausführen läßt, ist es sinnvoll,
daß er erfährt, wie ausgelastet die einzelnen CPUs im Netz sind.
Das Dilemma dabei ist immer, daß man eigentlich erst nach dem
Prozeßablauf abschätzen kann, wie groß sein Betriebsmittelbedarf
ist. Sehen wir uns dazu einige Lastenausgleichstrategien an:
* Lastenabstoßungsstrategie (auch Börsenalgorithmus genannt, weil
hier das bestes "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 Prozeß?
* Lastenanziehungsstrategie:
LOOP DO
Lastenmessung in Delta-t
IF Unterlast THEN an alle Knoten: Wer hat einen Prozeß 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
forpflanzen und dann dort eine Migrations-Arbeitsumgebung schaffen, die mit all
seinen Segmenten auf den anderen Rechnern kommunizieren kann.
Die Lastausgleichstrategien 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,
daß bei jeder Migration der komplette Adreßraum des Prozesse
mitkopiert werden muß (bei Teilmigration ist auch eine
copy on reference-Aufforderungsstrategie möglich). Und wie soll die IPC
danach weitergeführt werden?
* Weiterleitungs-Nachrichtenfluß: Statthalter könnten im alten
Knoten bleiben, die alle ankommende Nachrichten an den neuen Knoten
weiterleiten.
* Vorab-Informations-Nachrichtenfluß: vor der Migration werden alle
Partnerprozesse über den neuen Knoten informiert.
* Verlust und Recovery-Nachrichtenfluß: nach der Migration werden alle
Partnerprozesse über den neunen Knoten informiert - dadurch gehen alle
Nachrichten dazwischen verloren, die jedoch u.U rekonstruierbar sind.
Zu merken: Verteilte Betriebssysteme sollten Prozeßkontrollblöcke
besitzen, die für verschiedene Rechnerarchitekturen benutzbar sind.
Das Task-Thread-Prozeß-Verwaltungsmodell erlaubt die parallele
Verarbeitung von Prozessen innerhalb einer Verwaltungseinheit. Dies
erhöht bei heavyweight-Tasks die Geschwindigkeit, aber auch den
Verwaltungsaufwand - lightweigt-Tasks scheinen uns daher die angemesseneren
zu sein. Auch was das Scheduling angeht, heißt Einfachheit die
Devise: Lastenausgleichstrategien über globale Scheduler und Migration
von Prozessen kosten mehr, als daß sie nutzen - auf sie sollte
verzichtet werden.
8. Dateiverwaltung
(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 ->
Transaktions->Service
Anders als bei herkömmlichen Betriebsystemen muß in einem verteilten
Betriebsystem 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 wo ganz anders befinden. Bis zu einem
gewissen Grad ist dieses Prinzip bereit in UNIX zu finden, wo es
Diskless-Workstations gibt, die auf Fileserver angewiesen sind (nur bis zu
einem gewissen Grad deshalb, weil die hier verwendeten Datei-Transfersysteme
wie FTAM und FTP nicht transparent arbeiten).
(2) Organisation von verteilten Dateisystemen:
* zentraler Fileserver, der die komplette Dateiverwaltung
übernimmt.
* replizierter Fileserver, der zwar sklalierbar ist, aber Update-Probleme
besitzt und wo der richtige für den Client schwerer zu finden ist.
* vollständig verteiltes Dateisystem: alle Rechner können
Filreserver sein für ihr lokales Umfeld, sind also mit eigenem Dateisystem
ausgestattet.
(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 reduzuiert werden, wenn Cache-Techniken eingesetzt werden).
* DÜ übers Netz (kommt bei remoten Zugriff hinzu).
* CPU-Zeit zur Bearbeitung der Informationen.
(4) Dateinamensfindung: Das Suchen von Dateinamen im Netz kann der Client
übernehmen, doch sollte dazu besser ein Fileserver 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 Fileservern
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.
(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 Prozeß 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 muß sichergestellt
sein, daß Prozesse, die er anbietet, idempotent sind.
* Session-Semantik: wenn hier jemand eine Datei beschreibt, bekommen dies
nur die lokalen Prozesse unmittelbar mit, weil die remoten mit Duplikaten
arbeiten. Der Dateiserver kann statless oder stateful sein.
* Immutable Semantik: wenn hier jemand eine Datei beschreiben will, so
muß 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 Schreiblesekopf u.ä. Ein Absturz kann das Netz
zusammenbrechen lassen. Aber auch ein stateless Fileserver ist denkbar.
(6) Caching: Hier wird das Lokalitätsprinzip ausgenutzt, also die
Tatsache, daß ein Prozeß meistens Dateien beansprucht, die sich in
unmittelbarer Nähe zu einander befinden. Daher ist es sinnvoll bei remoten
Zugriffen nicht nur den einen Dienst, sondern gleich ganze Blöcke oder
Seiten in den lokalen Speicher des remoten Rechners (oder des eigenen) zu
kopieren.
Wichtig sind dabei Validierungs-/Updatetrategien, die am besten vom
Dateiserver durchgeführt werden, um sicherzustellen, daß der
Cache-Inhalt mit dem Platteninhalt übereinstimmt. Hierzu bieten sich
an:
* write throug: Jedes Cachebeschreiben bewirkt Plattenbeschreiben.
* delay write: schreiben vom Cache auf Platte z.B. alle 30 Sekunden.
* write-on-close
Zu merken: auf das Schichtprinzip kann bei verteilten Betriebssystemen nicht
verzichtet werden. Vollständig verterteilte Dateiserver sind zentralen
vorzuziehen. Zur Dateinamensfindung sollten fremde Directories in den eigenen
Directorybaum mountbar sein, die Suche übernehmen die Fileserver über
rekursives Lockup der Pfade. Für den Dateizugriff sind stateless Fileserver
vorzuziehen, die nach der Transaction-Semantik arbeiten. Und auf Caching - v.a.
beim remoten Server-Rechner - sollte wohl auch nicht verzichtet werden.
9. Zusammenfassung
In den obigen Kapiteln wurde beschrieben, auf welchee verschieden Weisen sich
verteilte Betriebssysteme realisieren lassen. Im Anschluß zu jedem Kapitel
wurde dabei die Favorisierung bestimmter Eigenschaften vorgenommen, die wir
hier nun in Form einer Checkliste für ein optimales verteiltes Betriebsystem
auflisten wollen:
* Client/Server-Interaktionsmuster
* Client/Server-Kooperations-Organisation
* Broadcastmedium
* Load Sharing-Server
* Synchrone Kommunikation
* auftragsorientiertes Kommunikationsmodell
* Primitive-Austausch
* verkettete Nameserver
* Weitergabe-Methode zur Namensauflösung
* abhörsicheres Subnet
* 2-Wege-Eingangsautorisierung
* Zugriffs-Capabilities
* asymetrische Kodierung (öffentliche Schlüssel)
* Autorisierungsserver mit Nameserver kombiniert
* einmalige Nachrichten zur Entschlüsselungsprobe
* heterogentitäts-adaptive Prozeßkontrollblöcke
* Task-Thread-Prinzip mit Leightweigt-Tasks
* globales Scheduling ohne Lastenausgleich und Migrationsstrategien
* Schichtkonzept
* vollständig verteilte Dateiserver
* Mountbare Directories
* stateless Dateiserver
* Transaction-Semantik
* Caching beim remoten Server
|