Kommunikation und Synchronisation
ÜBERSICHT
1. Begriffe
2. Kooperationsformen
3. Kommunikationsmuster
4. Kommunikation und Synchronisation: Konzepte
5. Basisoperationen für den Nachrichtentransfer
6. Synchroner und asynchroner Nachrichtenaustausch
7. Verbindungslose- und verbindungsorientierte Kommunikation
8. End-to-End-Argumente
9. Quellen
1.
Begriffe
Sequentielles Programm: Eine
Liste von Anweisungen, die sequentiell ausgeführt werden.
Prozess: Die Ausführung
eines sequentiellen Programms
Nebenläufiges Programm:
Zwei oder mehr sequentielle Programme, die als nebenläufige
Prozesse ausgeführt werden. Hier ist Synchronisation
erforderlich. Man unterscheidet folgende zwei Fälle bei
nebenläufigen Prozessen: Prozesse nutzen einen gemeinsamen
Prozessor und Prozesse nutzen unterschiedliche Prozessoren,
d.h. werden echt parallel ausgeführt. Bei Prozessen,
die unterschiedliche Prozessoren benutzen, unterscheidet man
Multiprocessing, Parallel Processing und Distributed Processing.
Bei Multiprocessing haben die
Prozessoren gemeinsamen Speicher.
Unter Parallel Processing versteht
man Prozessoren, die keinen gemeinsamen Speicher haben aber
über ein schnelles, Interkonnektionsnetzwerk verbunden.
Falls Prozessoren keinen gemeinsamen
Speicher haben und über ein Rechnernetz (LAN, MAN, WAN)
miteinander verbunden sind, so spricht man von Distributed
Processing.
Kooperation: Wenn Prozesse zusammenarbeiten, um ein gemeinsames
Ziel zu errechen, so spricht man von Kooperation.
Konkurrenz: Prozesse konkurrieren
um die Benutzung von Ressourcen.
Kooperation und Konkurrenz schließen
einander nicht aus.
Kommunikation: Kommunikation
ist der Austausch von Information zwischen Prozessen.
Synchronisation: Prozesse synchronisieren
sich auf Ereignisse, wobei Prozesse Ereignisse herbeiführen
können. Prozesse können bis zum Eintritt eines Ereignisses
verzögert werden.
2. Kooperationsformen
2.1 Produzenten/Konsumenten-Systeme
Der Konsument nimmt Daten auf,
die vom Produzenten erzeugt wurden. Hier genügt ein unidirektionaler
Kanal.
2.2 Pipeline-Modell
Eine Pipeline kann man sich als
ein unidirektionalen Kanal vorstellen.
2.3 Client/Server-Modell
Der Server bietet seinen Service
einer Menge a priori unbekannter Klienten an. Service bezeichnet
die Software-Instanz, die auf einer oder mehreren Maschinen
ausgeführt wird. Der Server ist eine Maschine, die Service-Software
ausführt. Der Klient ist der Nutzer eines Services.
3. Kommunikationsmuster
3.1 1-to-1
Senden an genau einen Prozess.
3.2 Rundsenden (broadcast)
Senden an alle Prozesse
3.3 Mehrfachsenden (multicast)
Senden an eine Gruppe G von Prozessen.
Es gilt : 1 < |G| < n
4. Kommunikation und Synchronisation:
Konzepte
Es gibt zwei Möglichkeiten
Kommunikation und Synchronisation zu realisieren. Der erste
Ansatz ist mittels gemeinsamen Speicher. Techniken dazu sind
Semaphore, Monitore und Pfadausdrücke.
Der zweite Ansatz ist Kommunikation und Synchronisation mittels
Nachrichtenaustausch. Da gibt es die Konzepte von Nachrichten,
RPC, Rendezvous und virtuellem gemeinsamen Speicher.
Beispiel: In dem oberen Beispiel findet die Kommunikation
durch Schreiben und Lesen des gemeinsamen Speichers statt.
Synchronisiert wird auf Zustandsänderungen des gemeinsamen
Speichers. Als Synchronisationskonzepte kommen hier zum Einsatz:
Semaphore, Monitore, Pfadausdrücke usw.
Beispiel: Kommunikation und Synchronisation findet durch den
Austausch von Nachrichten statt - Nachrichtenaustausch = Kommunikation
+ Synchronisation. Kommunikation durch das Senden und Empfangen
von Nachrichten. Synchronisiert wird auf Sende und Empfangsereignisse.
Wir verfolgen den Ansatz der
Kommunikation und Synchronisation mittels Nachrichtenaustausch.
Auf den Ansatz "gemeinsamer Speicher" wird hier
nicht näher eingegangen.
5. Basisoperationen für
den Nachrichtentransfer
Für den Nachrichtenstransfer
gibt es zwei Basisoperationen, nämlich send und receive.
send expression to destination
Die Nachricht enthält den
Wert von expression. Mit destination spezifiziert man das
Ziel oder die Ziele.
receive variable from source
Die Nachricht wird in variable
empfangen. Source spezifiziert, von welcher Quelle die Nachricht
kommen soll.
Aus der obigen Abbildung ist zu entnehmen, dass die Operationen
nochmals in blockierend und nicht-blockierend unterteilt werden.
Doch zuvor noch grundsätzliche
Gedanken. Wohin kann die Sendevariable kopiert werden?
Beispiel 1:
Beispiel 2:
Die Beispiele zeigen zwei Möglichkeiten.
Beim ersten Beispiel wird die Sendevariable direkt in die
entsprechende Empfangsvariable kopiert. Das zweite Beispiel
zeigt den Fall, in der die Sendevariable in einen Puffer kopiert
wird.
nicht-blockierende Sendeoperation
Der Sender wird nur für die Dauer des Kopierens verzögert.
blockierende Sendeoperation
Der Sender wird so lange verzögert, bis die entsprechende
Empfangsanweisung ausgeführt wird.
blockierende Empfangsoperation
Der ausführende Prozess wird so lange blockiert, bis
Nachricht eingetroffen ist.
nicht-blockierende Empfangsoperation
Der ausführende Prozess wird keinesfalls blockiert. Hier
gibt es zwei Varianten.
Variante 1: Falls eine Nachricht vorhanden ist, wird sie empfangen,
sonst Return Code.
Variante 2: Receive signalisiert die Empfangsbereitschaft.
Wenn die Nachricht eintrifft, wird der Empfangsprozess unterbrochen.
6. Synchroner und asynchroner
Nachrichtenaustausch
6.1 Synchroner Nachrichtenaustausch
Beim synchroner Nachrichtenaustausch
benutzen Sender und Empfänger blockierende Sende- und
Empfangsoperationen. Wichtig ist, das hier keine Pufferung
notwendig ist. Denn die Nachricht kann direkt vom Senderadressraum
über das Netzwerk in den Empfängeradressraum kopiert
werden.
Woher weiß aber der Sender,
wann er Nachrichten senden kann bzw. eine Nachricht empfangen
wurde?
Protokoll1: send blockiert bis
Bestätigung für Nachricht empfangen wurde
Prozess P1 und P2 tauschen synchron Nachrichten. Beide Operationen
sind blockierend. Durch die INPUT(P2) Nachricht, weiß
der Sender, dass er die Nachricht senden darf. Mit ACK bestätigt
P2 den Erhalt der Nachricht.
Protokoll 2: send blockiert bis
receive aufgerufen wurde
Bei Protokoll 2 fehlt die ACK, die Bestätigung für
den Erhalt der Nachricht.
6.2 Asynchroner Nachrichtenaustausch
Beim asynchronen Nachrichtenaustausch
benutzt mindestens einer der Prozesse eine nicht-blockierende
Sende- oder Empfangsoperation.
Protokoll 1:
Damit asynchroner Nachrichtenaustausch
überhaupt funktioniert, ist prinzipiell unendlich großer
Puffer erforderlich. Das Protokoll 1 zeigt so einen Fall.
So ist es z.B. möglich, dass P1 mit send unendlich viele
Nachrichten in den Puffer schreibt. Aus diesem unendlich großen
Puffer kann sich P2 bedienen.
Protokoll 2:
Es handelt sich hier um das selbe Protokoll wie Protokoll
1. Hier ist nur der Fall dargestellt, in der P2 auf eine Nachricht
wartet. Dies kann passieren, wenn der Puffer leer ist. In
dem Augenblick, nachdem P1 etwas in den Puffer geschrieben
hat, kann P2 die Nachricht auslesen und ist nicht mehr blockiert.
Man stelle sich den realistischen
Fall vor, in der Puffer endlich groß ist. Hier wird
der Sender bei vollem Puffer so lange blockiert, bis wieder
Speicher frei wird. Man spricht von pufferblockierendem Senden.
Ein einfaches Protokoll dazu
ist das Stop-and-wait-Protokoll. Der Puffer kann genau eine
Nachricht aufnehmen. Die Pufferung findet beim Empfänger
statt. Eine Verallgemeinerung des Stop-and-wait-Protokolls
ist der Fenstermechanismus.
Beschreibung des Stop-and-wait-Protokolls:
1. Wenn der Puffer leer ist,
so kann P1 die Nachricht in den Puffer kopieren und wird nicht
blockiert.
2. Falls P1 eine Nachricht senden
möchte und der Puffer nicht leer ist, wird er solange
blockiert, bis ein ACK von P2 eintrifft. Mit ACK signalisiert
P2, dass der Puffer überschrieben werden darf.
3. Falls Puffer belegt ist und
P2 empfangen möchte, so wird P2 nicht blockiert. Er muss
nur ein ACK an P1 schicken.
4. Falls Puffer leer ist und
P2 empfangen möchte, so wird P2 so lange blockiert bis
P1 eine Nachricht in den Puffer schreibt.
6.3 Synchroner vs. asynchroner
Datenaustausch
Bei asynchronem Datenaustausch
hat man ein Maximum an Flexibilität und Parallelität.
Allerdings ist eine Pufferung der Daten notwendig. Ebenfalls
ein Nachteil ist, dass komplexe Programme schwierig zu testen
sind.
Synchroner Datenaustausch erlaubt
einfache und verifizierbare Programme, hat aber den Nachteil
der Einschränkung der Parallelität. Es ist, wie
schon oben erwähnt, keine Pufferung notwendig.
7. Verbindungslose- und
verbindungsorientierte Kommunikation
Kommunikation wird in verbindungsorientierte
und verbindungslose Kommunikation unterteilt. Verbindungsorientierte
Kommunikation ist zuverlässig. Verbindungslose Kommunikation
ist im Prinzip unzuverlässig, kann aber auch zuverlässig
gemacht werden.
7.1 Verbindungslose Kommunikation
Bei der verbindungslosen Kommunikation
werden die Nachrichten als isolierte Einheiten übertragen.
Es findet keine Flusskontrolle statt, d.h. Einheiten können
sich überholen. Wie schon erwähnt ist verbindungslose
Kommunikation meist unzuverlässig, aber auch zuverlässige
Datagramme sind möglich.
Wie sieht ein Protokoll bei unzuverlässigen
Datagrammen aus?
Es sind einfachste Protokolle. P1 sendet P2 eine Nachricht.
Diese Nachricht kann verloren gehen, es können Duplikate
entstehen, die Reihenfolge kann verändert werden, die
Daten können unterwegs modifiziert werden. Weder P1 noch
P2 unternehmen etwas, um dies zu ändern.
Wie sieht ein Protokoll bei zuverlässigen
Datagrammen aus?
Hier sind komplexere Protokolle notwendig. Wie kann man Verlust,
Modifikation und Duplikate und Folgefehler erkennen?
Verlust lässt sich dadurch erkennen, dass ein ACK für
jedes übertragene Datagramm fällig wird. P1 sendet
eine Nachricht und startet einen Timer. Nun gibt es zwei Möglichkeiten,
nämlich das die Nachricht selbst verloren geht oder ACK
nicht ankommt. Bei beiden Möglichkeiten sendet P1 nach
Ablauf des Timers die Nachricht nochmals.
Falls ACK verlorengegangen ist, muss P2 Duplikate erkennen.
Dies kann mittels Nachrichten-IDs gelöst werden.
Modifikation wird dadurch erkannt, dass eine Prüfsumme
berechnet wird. Weicht sie vom erwarteten Wert ab, ist ein
Übertragungsfehler passiert.
Folgefehler kann man mittels fortlaufendender Nummerierung
erkenn, z.B. auch durch fortlaufende Nachrichten-IDs.
7.2 Verbindungsorientierte
Kommunikation
Bevor eine verbindungsorientierte
Kommunikation erfolgen kann, muss zuerst eine Verbindung aufgebaut
werden. Nach dem Datentransfer wir die Verbindung wieder abgebaut.
Verbindungsaufbau, Datentransfer und Verbindungsabbau wird
3-phasige Interaktion genannt.
Beim Verbindungsaufbau kann die
Qualität des Dienstes ausgehandelt werden. (Quality of
Service). Das sind z.B. Merkmale wie Durchsatz, Verzögerung
oder Fehlerwahrscheinlichkeit.
Bei einer verbindungsorientierten
Kommunikation wird zuverlässige Kommunikation in beide
Richtungen betrieben, d.h. kein Verlust, keine Duplikate,
keine Modifikation. Keine Folgefehler, d.h. Flusskontrolle
findet ebenfalls statt. Dies alles erfordert eine vergleichsweise
komplexe Protokolle.
Es sind zusätzliche Primitive
für den Verbindungsaufbau und -abbau nötig:
connect: Senden eines Verbindungswunsches
listen: Empfangen eines Verbindungswunsches
accept: Akzeptieren eines Verbindungswunsches
reject: Ablehnen eines Verbindungswunsches
disconnect: Abbau einer Verbindung usw.
Wichtige Protokollelemente:
Verbindungsaufbau durch das Three-Way-Handshake.
Verbindungsabbau
Fehlerkontrolle: Positive Acknowledgement
and Retransmit (PAR)
Sequenzkontrolle durch Sequenznummern
Fehlererkennung durch Prüfsumme
(z.B. CRC)
Flusskontrolle durch Fenstermechanismus
oder Credits
Zusätzliche Hinweise:
Ein Beispiel für den Fenstermechanismus
ist Sliding Windows.
ACK sind Bestätigungen.
NAK sind negative Bestätigungen.
Ein NAK kann z.B. von P1 an P2 gesendet werden, um anzudeuten,
dass zwar die Dateneinheit empfangen wurde aber die Fehlererkennung
einen Fehler festgestellt hat.
NAK dient hauptsächlich der Beschleunigung. Z.B. könnte
Prozess P2 auch so lange warten und kein ACK senden, bis P1
das fehlerhafte Packet nochmals sendet.
Falls ein Protokoll NAK nicht
implementier hat, so spricht man von Fehlerkontrolle mittels
PAR. Es gibt nur bei erfolgreichem Empfangen ein ACK, d.h.
der empfangende Prozess wartet bis Timeout beim Sender auftritt
und er ein erneutes Senden veranlasst.
Man spricht von Three-Way-Handshake,
falls der Verbindungsaufbau in drei Schritten erfolgt, so
wie dies beim Aufbau einer TCP-Verbindung der Fall ist.
7.3 Verbindungslose- vs.
verbindungsorientierte Kommunikation
Argumente für verbindungsorientierte
Kommunikation
Einfaches und mächtiges
Paradigma. Es vereinfacht die höheren Schichten und führt
somit zur Entlastung der Endsysteme. Verbindungslose Kommunikation
ist für ein breites Spektrum von Anwendungen geeignet.
Argumente für (unzuverlässige)
verbindungslose Kommunikation
Sie hat hohe Flexibilität
und geringe Komplexität. Für einige Anwendungen
(z.B. Echtzeitanwendungen, digitale Sprachübertragung)
ist hohe Performance wichtiger als fehlerfreie Übertragung.
Falls nur eine relativ kurze Interaktion gewünscht wird,
so ist der Kostenanteil für Auf und Abbau von Verbindungen
hoch. "End-to-End-Arguments".
Was bedeutet "End-To-End-Arguments"?
8. End-to-End-Argumente
In geschichteten Systemen kann
die Realisierung einer Funktion in unteren Schichten überflüssig
sein, oder ihre Realisierung verursacht hohe Kosten.
Bei unzuverlässiger Kommunikation
können Fehler erst in oberen Schichten entdeckt und behandelt
werden. Zuverlässige Kommunikation ist teuere Kommunikation.
Der Grund liegt darin, dass End-to-End Recovery trotzdem notwendig
ist, obwohl viele Funktionen in unteren Schichten realisiert
werden. Dazu zählen z.B. Übertragungsfehler oder
Duplikatserkennung. Die Duplikatsunterdrückung im Server
z.B. erkennt und unterdrückt auch Duplikate des Transportsystems.
Z.B. kann auch eine End-to-End Verschlüsselung die Verschlüsselung
auf der Transport-Ebene überflüssig machen.
Was spricht gegen End-to-End-Argumente?
Wenn bestimmte Funktionen in
unteren Schichten realisiert werden, werden Fehler entdeckt.
Das spart Bandbreite und CPU- und Pufferressourcen.
Die Frage, welche Funktionen
wo realisiert werden sollen, hängt von der Art und Topologie
des Netzwerkes ab. Außerdem spielen Zuverlässigkeitsanforderungen
der Anwendungen eine wichtige Rolle.
Man kann einen Kompromiss schließen.
Das Transportsystem unterstützt zwei Dienstklassen, nämlich
einen allgemeinen zuverlässigen Dienst und einen effizienten
unzuverlässigen Dienst.
9. Quellen
[1] Skript Grundlagen Verteilte
Systeme; Prof. Dr. Kurt Rothermel - Abteilung Verteilte Systeme
an der Universität Stuttgart
|