Prozess-synchronisation
Prozesskommunikation Race Conditions, Semaphore Anwendungen Verklemmungen Prozesskommunikation (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Race conditions Beispiel: Kontoführung Paralleler Zugriff auf globale Variable C Parallele Prozesse von vielen Benutzern arbeiten gleichzeitig auf den Daten. Falls gleichzeitig zwei Benutzer auf das gleiche Konto einzahlen möchten, so kann es sein, dass der Kontostand hinterher nicht stimmt. Ein solcher Fehler wird von keinem Kunden toleriert! 15:00 Uhr Konto C= 300 € 500 € einzahlen 100 € abheben 15:01 B := read(C) A := read(C) 15:02 A := A + 500 B := B -100 15:03 A write(C) 15:04 B write(C) Eine Fehlbuchung tritt nur auf, wenn Prozess den Prozess überholt („race condition“) Konto C = 200 € Zeit (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Situation: Warteschlangeneintrag eines PCB Race conditions Situation: Warteschlangeneintrag eines PCB Einhängen A Aushängen B (1) Lesen des Ankers: PointToB (1) Lesen des Ankers: PointToB (2) Setzen des NextZeigers:=PointToB (2) Lesen des NextZeigers:PointToC (3) Setzen des Ankers:=PointToA (3) Setzen des Ankers:=PointToC Problem: („Race conditions“: kontextbedingt, nicht-wiederholbare Effekte durch „überholende“ Prozesse) a) Unterbrechung beim Aushängen von B durch Einhängen von A Prozeß A ist weg! b) Unterbrechung beim Einhängen von A durch Aushängen von B Prozeß B bleibt erhalten! (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synchronisation: Forderungen Zwei Prozesse dürfen nicht gleichzeitig in ihren kritischen Abschnitten sein (mutual exclusion). Jeder Prozeß, der am Eingang eines kritischen Abschnitts wartet, muß irgendwann den Abschnitt auch betreten dürfen: kein ewiges Warten darf möglich sein (fairness condition). Ein Prozeß darf außerhalb eines kritischen Abschnitts einen anderen Prozeß nicht blockieren. Es dürfen keine Annahmen über die Abarbeitungsge-schwindigkeit oder Anzahl der Prozesse bzw. Prozessoren gemacht werden. (Dijkstra 1965) (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synchronisierung: erster Versuch Naiver Ansatz: mutual exclusion mit globaler Variablen Wartesperre errichten, bis kritischer Abschnitt frei Initial dran=1 Prozeß 1 Prozeß 2 . . . WHILE dran1 DO NoOp END; WHILE dran2 DO Kritischer Abschnitt dran := 2; dran := 1; Funktion: Anfangs ist die globale Variable mit dran=1 initialisiert. Kritischer Abschnitt in Prozeß1 frei, in Prozeß2 blockiert. Danach umgekehrt. Wenn der eigene Prozeß erneut den krit. Abschnitt besuchen will, so geht dies nicht: Er hat sich selbst blockiert, solange, bis der andere Prozeß seinen Abschnitt durchlaufen hat, evtl. auf ewig (grau schraffierte Bereiche sind ununterbrechbar). Problem: nur wechselseitige Benutzung des kritischen Abschnitts möglich, Prozeß blockiert sich nach Ausführung selbst. (nicht-notw. Blockade sowie fairness sind verletzt bei ewigem Warten) (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synchronisierung: zweiter Versuch Verbesserung: Zugang nur blockiert beim Aufenthalt in krit. Abschnitt Prozeß 1 Prozeß 2 . . . WHILE drin2=TRUE DO NoOp END ; drin1 := TRUE; WHILE drin1= TRUE NoOp END; drin2 := TRUE; Kritischer Abschnitt drin1 := FALSE; drin2 := FALSE; Idee: Gegenseiter Ausschluß durch eigene Variable pro Prozeß. Problem: Initialisierung. Bei drin1=drin2=TRUE werden beide ewig blockiert. Bei drin1=TRUE, drin2=FALSE wird Prozeß 2 blockiert, obwohl Prozeß 1 nicht im krit. Abschnitt ist. Bei drin1=drin2=FALSE können beide gleichzeitig in ihre krit. Abschnitte gelangen. Problem: Initialisierung drin1=drin2=False keine mutual exclusion! drin1=True, drin2=False P2 ist blockiert ohne Sinn (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synchronisierung: Lösung Peterson 1981 Verbesserung: eine globale Variable, 2 Prozeß-Zustandsvariable. Initial Interesse1 = Interesse2 = FALSE Prozeß 1 Prozeß 2 . . . Interesse1 := TRUE; Interesse2 := TRUE; dran := 1; WHILE dran=1 AND Intere s se2=TRUE DO NoOp END; dran := 2; WHILE dran=2 se1=TRUE Kritischer Abschnitt Interesse1 := FALSE; Interesse2 := FALSE; Idee: 2 globale Variable; Interesse1=Interesse2=FALSE initialisiert. Ist einer von beiden außerhalb der grauen Zone, so kann der andere ohne Probleme den krit. Abschnitt durchlaufen. Einer blockiert nur, wenn der andere ebenfalls die graue Zone betreten hat. Allerdings kann nur eine der beiden Blockadebedingungen zu einem Zeitpunkt erfüllt sein, so daß der andere Prozeß weitergehen kann. Am Ende „erlöst“ er den anderen, wartenden Prozeß bzw. stellt die Anfangsbedingung wieder her. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Lösung: Signale und Semaphoren Peterson: Synchronisierung durch Signale (Interesse) Allgemein: Das Semaphor (Signalbarken, Dijkstra 1965) Passieren P(s) waitFor (signal) Aufruf vor krit. Abschnitt, Warten falls besetzt Verlassen V(s) send (signal) Aufruf nach krit. Abschnitt, Aktivieren eines wart. Prozesses Beispiel: paralleles Hochzählen z = 1, 2, 3, ... z global Prozeß 1 Prozeß 2 . . . P(s) V(s) z :=z+1; WriteInteger(z) warten freigeben (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Implementierung Semaphoren: busy wait Software Pseudo-Code Semaphore=Zähler, initial s=1 PROCEDURE P(VAR s:INTEGER) BEGIN WHILE s<=0 DO NoOp END; Ununterbrechbar! s:=s-1; END P; PROCEDURE V(VAR s:INTEGER) s:=s+1; Ununterbrechbar! END V; Problem: spin locks können fairness verletzten, wenn die Zeitscheibe eines niedrig-prio Prozeß im krit. Abschnitt zu Ende geht (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Implementierung Semaphoren: Schlafen Software Pseudo-Code Datenstruktur PROCEDURE P(VAR s:Semaphor) BEGIN s.value:=s.value-1; IF s.value < 0 THEN einhängen(MyID,s.list); sleep; END; END P; PROCEDURE V(VAR s:Semaphor) VAR PID: ProcessId; PID:=aushängen(s.list); wakeup(PID); s.value:=s.value +1; END V; TYPE Semaphor = RECORD value: INTEGER; list : ProcessList; END; Initial: s.value:=1 Im Unterschied zur Implementierung auf der vorigen Folie wird hier auf <0 abgefragt, da die Dekrementierung bereits vor der Abfrage vorgenommen wird. Nach dem 1. Prozeß ist s.value=0, nach dem 2. Prozeß <0. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Beispiel: Geldtransaktion Sie überweisen 2000 €. Atomare Aktionen Beispiel: Geldtransaktion Sie überweisen 2000 €. Abbuchung 2000 € Empfänger-Gutbuchung 2000 € Wo ist das Geld? Keine oder neue Überweisung = Verlust! Forderung: „Atomare Aktion“ Entweder vollständige Transaktion oder gar keine ! („roll back“ bei Abbruch) Computerabsturz ! (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
HW-Implementierung: Atomare Aktionen Interrupts ausschalten (Probleme: timer, power failure, I/O) Atomare Instruktionsfolgen Test And Set (test and set lock) PROCEDURE TestAndSet(VAR target:BOOLEAN): BOOLEAN VAR tmp:BOOLEAN; tmp:=target; target:= TRUE; RETURN tmp; END TestAndSet; Swap PROCEDURE swap(VAR source,target: BOOLEAN) tmp:=target; target:=source; source:=tmp; END swap; Fetch And Add PROCEDURE fetchAndAdd(VAR a, value:INTEGER):INTEGER VAR tmp:INTEGER; tmp:=a; a:=tmp+value; RETURN tmp; END fetchAndAdd; (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Implementierung Semaphoren: busy wait Software Pseudo-Code Semaphore=Zähler, initial s=1 PROCEDURE P(VAR s:INTEGER) BEGIN WHILE FetchAndAdd(s,-1)<= 0 Ununterbrechbar! DO FetchAndAdd(s,+1) END END P PROCEDURE V(VAR s:INTEGER) FetchAndAdd(s,+1) Ununterbrechbar! END V Probleme? (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Anwendung Multiprozessoren Implementierung der Semaphor-Operationen, Anwendung Multiprozessorsynchronisation VAR s: INTEGER; (* Semaphore, initial = 1*) PROCEDURE P(s); PROCEDURE V(s); BEGIN BEGIN LOOP FetchAndAdd(s,1) END V; IF (FetchAndAdd(s,-1) >= 1) THEN RETURN END; FetchAndAdd(s,1); ENDLOOP; END P; s = 1, WHILE s<1 DO NoOp END; Zusätzlich zu der Warteschleife mit FetchAndAdd (FAA) existiert eine WHILE-Schleife- Warum? Betrachten wir dazu den Fall, bei dem drei Prozessoren P(s) zur gleichen Zeit die Prozedur durchlaufen, wobei initial s=1 sei. Die drei Prozessoren sollen als Rückgabe für s die Werte 1,0 und –1 erhalten, wobei zum Schluß s=-2 gesetzt wird. Der erste Prozessor betritt und verlässt den kritischen Abschnitt, die beiden anderen warten in der Schleife. Soweit, so gut. Angenommen, nach dem IF-statement findet immer ein Prozesswechsel statt. Prozessor 2 hat nun mit der ersten FAA gerade erst den Semaphor s auf –1 erniedrigt, wenn der erste Prozessor seine V()-Operation durchführt und damit den Semaphor auf s=0 erhöht. Würde nun Prozessor 2 die zweite FAA-Instruktion durchführen und so auf s=1 erhöhen, so könnte der Prozessor, der danach die FAA als erster durchläuft, normal die P()-Operation verlassen. Diese Gelegenheit kann aber durch den 3. Prozessor verhindert werden, indem er die FAA durchläuft noch bevor der 2. Prozessor durchlaufen hat und damit den Semaphor wieder auf –1 erniedrigt, so dass er anschließend vom 2. Prozessor nur auf 0 statt auf 1 erhöht wird. So ist durch die Sequenz (timing) [P3, P2, P2, P3], ... eine alternierende Sequenz für den Semaphor mit s=0,–1,0,–1, ... denkbar, in der der Semaphor nie den richtigen Wert hat, um einen der Prozessoren aus der Warteschleife zu entlassen: Die beiden Prozessoren bleiben blockiert, obwohl der kritische Abschnitt frei ist. Dies wird nun durch die WHILE-Schleife verhindert, da hier s nur gelesen und nicht verändert wird, so daß alle „Verlierer“-Prozesse zunächst einfach warten, ohne den Weg für andere blockieren zu können. -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, P1 P2 P1 P3 P2 P2 P3P3 P2 P2 .... (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Frage Angenommen, Sie haben 3 Prozesse und 2 kritische Abschnitte pro Prozess. Wieviele Semaphore benötigen Sie? 2 3 6 12 Code A Krit. Abschn. Code B Code C (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
memory Prozesse Semaphoren: Unix lockf Sperren Dateizugriff P(s) lock file memory msem_init Semaphorinit. zumSpeicherzugriff msem_lock Sperren eines Semaphors P(s) msem_unlock Entsperren eines Semaphors V(s) msem_remove Entfernen eines Semaphors Prozesse semctl Semaphorkontrolloperationen semget hole Semaphorwert semop Semaphoroperation (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Semaphore: Windows NT Prozesse CreateSemaphore() Erzeugen OpenSemaphore() Initialisieren WaitForSingleObject(Sema,TimeOutVal) P(s) ReleaseSemaphore() V(s) Threads Semaphore = Type CRITICAL_SECTION InitializeCriticalSection(S) EnterCriticalSection(S) P(s) LeaveCriticalSection(S) V(s) Kernprozesse Spin locks: keine Referenzen zu Disk-Speicher, keine traps & syscalls (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synchronisierung: Threads und Objekte Zwei Threads innerhalb eines Prozesses erzeugen das gleiche Objekt. Die Methoden beider Objekt-Instanzen greifen auf die gleichen globalen Daten (Attribute) zu. Chaos, wenn beide Threads auf die globalen Daten zugreifen. Problem: Object (Instanz 1) Thread 1 Globale Daten (static) Object (Instanz 2) Thread 2 (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Lösung: Prozeßgruppen Mögliche Lösung: Sperrung der Objekte, Serialisierung des Zugriffs (marshalling) Nachteil: keine Parallelaktivitäten möglich! Windows NT: explizite Zuordnung der Threads zu Objektmengen (Apartments) Apartment C Apartment B Apartment A Prozess Y Prozess X Objekt 1 Objekt 2 t3 t2 t1 t4 t5 t6 t7 (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Lösung: Threadgruppen in NT main STA Für jedes Objekt Speicherung des Threading-Modells (STA, MTA,both) in der Registrierung. MTA nur bei lokalen Daten ! Thread 1 Objekt 1 Objekt 2 Marshalling Single-Threaded Apartment STA Thread 2 Objekt 3 Prozess Marshalling Multi-Threaded Apartment MTA Thread 3 Thread 4 Objekt 4 Marshalling = Zugbildung (Rangierbahnhof) (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozesskommunikation Race Conditions, Semaphore Anwendungen Verklemmungen Prozesskommunikation (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Anwendung: Synchr. von Prozessen Präzedenzgraph Implementierung mit Semaphoren PROCESS A: TaskBodyA; V(b); V(c); END A; PROCESS B: P(b); TaskBodyB; V(d1);V(e); END B; PROCESS C: P(c); TaskBodyC; V(d2); END C; PROCESS D: P(d1); P(d2); TaskBodyD; END D; PROCESS E: P(e); TaskBodyE; END E; Globale Variable b,c,d1,d2,e mit 0 initialisieren. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synch. Erzeuger-Verbraucher Naiver Ansatz Initial: used = 0 Erzeuger Verbraucher Umschaltung LOOP LOOP produce(item) IF used=0 THEN sleep(); IF used=N THEN sleep(); getFromBuffer(item); putInBuffer(item); used := used-1 used := used+1; IF used = N-1 IF used=1 THEN wakeup(Erzeuger ); THEN wakeup(Verbraucher ); consume(item); END LOOP END LOOP Problem: race condition innerhalb der Flusskontrolle bei Umschaltung nach „used=0“ Pufferfüllung, dann ewiges Schlafen beider Prozesse. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synch. Erzeuger-Verbraucher Lösung Signal speichern. Aber: unbekannte Prozesszahl...? Semaphor einführen: belegtePlätze := 0, freiePlätze := N, mutex := 1 Erzeuger Verbraucher LOOP LOOP produce( item) P(belegtePlätze); P(freiePlätze); P( mutex); P( mutex); getFromBuffer( item); putInBuffer( item); V( mutex); V( mutex); V(freiePlätze); Die Lösung besteht darin, Semaphoren als Zähler einzuführen. Das Semaphor „freiePlätze“ regelt die endliche Länge des Puffers, wird vom Erzeuger runtergezählt und blockiert die Produktion, sobald N items im Puffer sind. Das Semaphor „belegtePlätze“ regelt ebenfalls die endliche Länge des Puffers und blockiert den Konsum, sobald keine items im Puffer mehr sind. Das Semaphor „mutex“ regelt die mutual exclusion und verhindert, daß die Kritischen Abschnitte, die den Pufferzugriff enthalten, von mehr als einem Prozeß gleichzeitig benutzt werden. V(belegtePlätze); consume( item); END LOOP END LOOP krit. Abschnittskontrolle + Flusskontrolle durch Semaphor (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
readers/writers - Problem Aufgabe: Koordination Lesen-Schreiben von Dateien Erstes readers/writers-Problem (Vorrang für Leser) Ein Leser soll nur warten, falls ein Schreiber bereits Zugriffsrecht zum Schreiben bekommen hat. Dies bedeutet, daß kein Leser auf einen anderen Leser warten muß, nur weil ein Schreiber wartet. Problem: Schreiber wartet ewig (verhungert!) Zweites readers/writers-Problem (Vorrang für Schreiber) Wenn ein Schreiber bereit ist, führt er das Schreiben so schnell wie möglich durch. Wenn also ein Schreiber bereit ist, die Zugriffsrechte zu bekommen, dürfen keine neuen Leser mit Lesen beginnen. Problem: Leser wartet ewig (verhungert!) (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Synchronisation readers/writers Semaphor ReadSem : Semaphor für Lese-Strategie WSem : Mutex f. Schreibvorgang Lesen Schreiben P(ReadSem); readcount:=readcount+1; IF readcount=1 THEN P(WSem) END; V(ReadSem); . . . Reading_Data(); readcount:=readcount-1; IF readcount=0 THEN V(WSem) END; P(WSem); . . . Writing_Data(); V(WSem); Initial ist readcount=0. Der erste Leser wird auf WSem nur blockiert, falls ein Schreiber im kritischen Abschnitt ist. Alle andere Leser warten auf ReadSem. Außerdem: Warten sowohl ein Leseprozeß als auch ein Schreibprozeß auf WSem, so entscheidet der Scheduler, welcher von beiden bei der Operation V(WSem) aufgeweckt wird. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Multiprozessor-Synchronisation Warteschlangenmanagement beim NYU-Ultracomputer (1983) FIFO-Ringpuffer im shared memory Schutz der InSlot/OutSlot-Zeiger mittels FetchAndAdd Puffermanagement full/empty RingBuf[0] RingBuf[N-1] RingBuf[1] InSlot OutSlot Init: 0 Init: 0 Fix InUse (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Multiprozessor-Synchronisation Ein/Aushängen bei der ready-queue Einhängen Aushängen IF InUse >= N IF Fix <= 0 THEN Full:=TRUE; RETURN THEN Empty:=TRUE; RETURN END ; END ; IF FetchAndAdd(InUse,1)>=N IF FetchAndAdd(Fix,-1)<=0 THEN THEN FetchAndAdd(InUse,-1); FetchAndAdd(Fix,1); Full:=TRUE; RETURN Empty:=TRUE; RETURN END ; END ; MyInSlot:=FetchAndAdd MyOut Sl ot:=FetchAndAdd (InSlot,1)MOD N; (OutSlot,1)MOD N ; Designentscheidungen: Pro Slot zwei Semaphore (initial 1), um wechselweises Ein-/Aushängen pro Slot zu erreichen. Pufferüberlaufregelung über full/empty: Keine direkte Verwendung von (InSlot-OutSlot), da nicht zuverlässig. Stattdessen Maxwert „InUse“ bzw. Minwert „Fix“ in einer Vorprüfung am Anfang des Ein- bzw. Aushängens, ähnlich dem Beispiel für Multiprozessor-Sync. Im grauen Bereich wird der Pufferüber/unterlauf geregelt, danach der genaue Puffer-Slot festgestellt. P ( InSem[ MyInSlot]); P ( OutSem[ MyOutSlot]); RingBuf[ MyInSlot]:= data; data:= RingBuf[ MyOutSlot]; V ( OutSem[ MyInSlot]); V ( InSem[ MyOutSlot]); FetchAndAdd(Fix,1); FetchAndAdd(InUse,-1); (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Frage Warum benötigt man bei jedem einzelnen Slot einen P/V-Mechanismus? Warum reicht der FetchAndAdd-Mechanismus nicht aus? Antwort FetchAndAdd ist für die Flußsteuerung nötig, aber reicht nicht für den Slot-Schutz etwa bei halb gefülltem Puffer. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Fehler bei Semaphoranwendung Mögliche Fehler bei P/V-Anwendung Vertauschung : alle sind nur gleichzeitig im krit. Abschnitt V(mutex); ... krit. Abschnitt ...; P(mutex); Replikation oder Weglassen: ewiges Warten P(mutex); ... krit. Abschnitt ...; P(mutex); Falsche Reihenfolge Erzeuger-Verbraucher-Problem Erzeuger P(freiePlätze); P(mutex); putInBuffer(item); V(mutex); V(belegtePlätze); Fehler: Vertauschung : alle sind nur gleichzeitig im krit. Abschnitt Replikation und Weglassen : ewiges Warten Vertauschung bei Erzeuger/Verbraucher: Warum problematisch? Antwort: Sei P1 im krit. Abschnitt der Erzeugers auf „frei“ blockiert. Dann kann es kein P2 geben, das beim Verbraucher mit V(frei) P1 wieder erlöst, da P2 dazu durch den mutex-Bereich gehen muß. Dieser ist aber gesperrt. Damit warten alle Prozesse ewig. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Monitore Lösung: Syntaktische Kapselung des kritischen Bereichs critical region Shared s (Semaphor) region s do <statement> mutual exclusion P(s); <statement>; V(s) conditional critical region region s when B do <statement> Abstrakter Datentyp Monitor interner, automatischer Schutz von Daten und Methoden durch Compiler MONITOR <name> (* lokale Daten und Prozeduren *) PUBLIC (* Methoden der Schnittstelle nach außen *) BEGIN (*Initialisierung *) ... ENDMONITOR (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Monitore: Erzeuger/Verbraucher MONITOR Buffer; Schnittstelle TYPE Item = ARRAY[1..M] of BYTE; VAR RingBuf: ARRAY[1..N] of Item; InSlot, (* 1. freier Platz *) OutSlot, (* 1. belegter Platz *) used: INTEGER; PUBLIC PROCEDURE putInBuffer(item:Item); BEGIN ... END; PROCEDURE getFromBuffer(VAR item:Item); BEGIN used:=0; InSlot:=1; OutSlot:=1; END MONITOR; Erzeuger Verbraucher LOOP produce( item) Buffer.putInBuffer( END Buffer.getFromBuffer( consume( item); (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Monitore: Flußkontrolle Erzeuger/Verbraucher: Zusätzliche Flußkontrolle nötig CONDITION s Signal(s) sendet Signal s an alle, die im Monitor warten Wait(s) wartet auf ein Signal Beispiel CONDITION frei, belegt PROCEDURE getFromBuffer(VAR item:Item); IF used=0 THEN wait(belegt)END item := RingBuf[OutSlot]; used := used-1; OutSlot := (OutSlot+1) MOD N; signal(frei); END getFromBuffer; PROCEDURE putInBuffer(item:Item) IF used=N THEN wait(frei)END; RingBuf[InSlot]:=item; used := used+1; InSlot := (InSlot+1) MOD N; signal(belegt); END putInBuffer; Im Unterschied zum naiven Ansatz haben wir allerdings nun die Abfragen zur Flußsteuerung mit gegenseitigem Ausschluß geschützt, so daß sich keine race conditions bilden können. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Monitore: Java Konstrukt synchronized (<expression>) <statement> Thread wartet, bis <expression> frei ist (automat. Semaphor). Innerhalb eines synchronized-Bereichs kann man zusätzlich mit den Methoden wait() auf ein Signal warten, das mit notify() gesendet wird, etwa zur Flusskontrolle. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozesskommunikation Race Conditions, Semaphore Anwendungen Verklemmungen Prozesskommunikation (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungen Beispiel (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungen (deadlocks) Beispiel: Datei bearbeiten und ausdrucken durch zwei Prozesse P1 P2 P2 hat den Drucker, will die Datei P1 hat die Datei, will den Drucker Drucker Auch in vollsychronisierten Betriebssystemen können Verklemmungen auftreten. Beispiel: Ein Prozeß nimmt eine Datei, liest ein Stück, gibt sie frei, druckt eine Stück und will dann weiterlesen. Ein anderer Prozeß nimmt die Datei, liest ein Stück und will drucken. Keiner gibt das Betriebsmittel frei, will aber das andere reservieren. Verklemmung! (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungen Notwendige und hinreichende Bedingungen (Coffman 1971) 1. Beschränkte Belegung (mutual exclusion) semaphorgeregelter Zugang 2. Zusätzliche Belegung (hold-and-wait) hat Drucker, will Datei 3. Keine vorzeitige Rückgabe (no preemption) behält Datei bzw. Drucker 4. Gegenseitiges Warten (circular wait) P1 wartet auf P2, P2 wartet auf P1 Typisch für Verklemmungen sind also folgende notwendige und hinreichende Bedingungen: (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
das Problem ignorieren, die Verklemmungen erkennen und beseitigen, Strategien: das Problem ignorieren, die Verklemmungen erkennen und beseitigen, die Verklemmungen vermeiden, die Verklemmungen unmöglich machen. eine der Bedingungen (1)–(4) verhindern (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungen Erkennen und beseitigen Anzeichen: viele Prozesse warten, aber CPU ist idle Prozesse müssen zu lange warten Betriebsmittelgraph (resource allocation graph) P 1 3 B 2 4 5 Interpretation des Graphen: Prozesse sind rund, Betriebsmittel, z.B. Drucker, sind viereckig. Pfeile von rund zu viereckig: Prozess will BM reservieren. Pfeile von viereckig zu rund: BM ist für Prozeß reserviert. Verklemmungsbedingungen erfüllt bei Zyklen im Graphen (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
verfügbare Zahl der BM vom Typ S Verklemmungen ES = Zahl der Betriebsmittel BM vom Typ S BKS = Zahl der von Prozeß K belegten BM vom Typ S CKS = Zahl der von Prozeß K geforderten BM vom Typ S verfügbare Zahl der BM vom Typ S Erkennungsalgorithmus für Verklemmung (0) Alle Prozesse sind unmarkiert. (1) Suche einen unmarkierten Prozeß K, bei dem für alle Betriebsmittel S gilt ASCKS . (2) Falls ein solcher Prozeß existiert, markiere ihn und bilde AS:=AS+BKS . (3) Gibt es einen solchen Prozeß ? DANN erneut (1) und (2). SONST STOP. Wenn ein unmarkierter Prozeß ex. : Verklemmung ex ! Der Algorithmus ist ein Test, ob ein Verklemmung (Deadlock) existiert. Der Markierungsprozeß prüft, ob eine Forderung erfüllt werden kann. Wenn ja, werden die BM auch als „verfügbar“ betrachtet. Sind am Ende alle Prozesse markiert, so kann es im nächsten Zeitschritt weitergehen (ungewiß, wie weit). Gibt es nichtmarkierte Prozesse, so können dessen Forderungen NIE erfüllt werden: Deadlock! Beispielrechnung (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungen Beseitigen Prozesse abbrechen z.B. verklemmten Prozess oder Prozess mit notw. BM Prozesse zurücksetzen auf check point und verklemmenden Prozess warten lassen Betriebsmittel entziehen von verklemmtem Prozess und warten, bis BM frei werden. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungsbedrohte Zustände vermeiden Verklemmungen Verklemmungsbedrohte Zustände vermeiden Test: Banker-Algorithmus (Dijkstra 1965) konservative Kreditausleihe eines Bankers:„Gib nur Kredit, wenn auch die Wünsche von anderen, vorgemerkten Kunden berücksichtigt werden können bei sichergestellter Rückzahlung“. „Verklemmung-JA“ = Verklemmungsbedrohung; sie muß nicht eintreten, wenn rechtzeitig BM zurückgegeben werden. Vermeidung: lehne eine neue BM-Anforderung ab, wenn der Test sagt, daß dies zu einer Verklemmung führen kann. Aber: Realität unbekannte BM-Forderungen der Zukunft Prozesszahl + BM-Zahl wechselt Laufzeit- + Speicherintensiver Algorithmus Der Algorithmus wird in der Praxis kaum eingesetzt, weil Bei den meisten Anwendungen ist die Zahl der maximal nötigen Betriebsmittel unbekannt. Die Anzahl der Prozesse im System ist dynamisch und wechselt ständig. Die Anzahl der verfügbaren Betriebsmittel ist ebenfalls veränderlich. Der Algorithmus ist laufzeit- und speicherintensiv. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungen Unmöglich machen Verhindere eine der vier Bedingungen 1. Beschränkte Belegung (mutual exclusion) BM fest nur einem Service-Prozess zuordnen 2. Zusätzliche Belegung (hold-and-wait) Nur ein BM pro Prozess (aber: lesen und drucken nicht gleichzeitig) Alle nötigen BM auf einmal anfordern (nicht bekannt und Vergeudung!) Alle BM zurückgeben vor Neuanforderung (Verwaltungsaufwand!) 3. Keine vorzeitige Rückgabe (no preemption) Vorzeitiger Prozess-Abbruch kann Inkonsistenzen verursachen 4. Gegenseitiges Warten (circular wait) Ordnungsrelation für BM einführen (Linearisierung) (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Verklemmungen Beispiele Ordnungsrelation Durchnummerieren der BM derart, dass nur höhere Nummern angefordert werden (nicht immer möglich). Anordnung in einer Hierarchie Prozeß A Prozeß E Prozeß A Prozeß C Supervision der record-Belegung (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Frage Angenommen, man kann bei der BM-Belegung einen Timer (Zeituhr) aufsetzen. Welche der vier notwendigen Bedingungen für Verklemmungen sind damit nicht erfüllt? Anwort: Bedingung 3: no premption, kein vorzeitiger Abbruch (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozesskommunikation Race Conditions, Semaphore Anwendungen Verklemmungen Prozesskommunikation (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation broadcast multicast unicast Verbindungsanzahl · (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Adressierung Eindeutige Adressierung: Qualifizierter ID mit IP Adresse = Prozeß-ID.RechnerName.Firma.Land z.B. 5024.hera.rbi.uni-frankfurt.de Problem: Prozeß wechselt ID bei Neustart, Aufgabe bleibt Lösung: logische ID, nicht physische. Beispiel: „Drucker“ Prädikatsadresse: Spezifikationen als Adresse (IF 386-CPU AND Java_installiert AND Drucker) = True: fühle dich angesprochen, sonst nicht. Arbeitsverteilung! (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation openConnection (Adresse) Verbindungsorientierte Kommunikation openConnection (Adresse) Feststellen, ob der Empfänger existiert und bereit ist: Aufbau der Verbindung send (Message)/ Nachrichtenaustausch; rece i ve(Message) closeConnection Leeren der Nachrichtenpuffer, Beenden der Verbindung Verbindungslose Kommunikation send (Adresse, Message)/ receive(Adresse, Message) (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Mailboxen Mailbox = Nachrichtenpuffer z.B. TYPE Mailbox = RECORD SenderQueue : tList; EmpfängerQueue : tList; MsgQueue : tList; MsgZahl : INTEGER; einhängen(tMsg): PROCEDURE; aushängen(tMsg): PROCEDURE; END Message = Kopf + Daten TYPE tMsg = RECORD EmpfängerAdresse: STRING; AbsenderAdresse: STRING; NachrichtenTyp: tMsgTyp; SequenzNummer : INTEGER; Länge: CARDINAL; Data: POINTER TO tBlock; // oder inline data END; Zugriff mit Semaphoren schützen! für Flußkontrolle Kopf Umstellung von physikalischen ID zu logischen Adressen, von ProzessID zu einer log. Aufgabe via Datenstruktur „Puffer“. Warteschlange für die Nachrichten Falls keine da, Warteschlange für Empfängerprozesse Falls mailbox voll, Warteschlange für Senderprozesse Einhängen/aushängen muß geschützt werden; sie implizieren ein sleep bzw. wake der Prozesse in den Warteschlangen. Nachrichten besitzen dabei einen feste Kopflänge + variablen Körper, je nach Aufgabe. Im Kopf ist auch die (abstrakte) Datenbeschreibung enthalten, die gleiche Interpretation auf unterschiedlichen CPU-Typen garantiert. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Pipes Unix pipe() unidirektionale Kommunikation „ Programm1 | Programm2 | .. | Programm N “ Windows NT CreatePipe() Bidirektionale pipes Globale Kommunikation: named pipes write() Programm 1 read() Programm 2 pipes werden folgendermaßen aufgebaut: Der shell-prozeß öffnet einen Kanal mit pipe() zwei Kindsprozesse werden erzeugt . Der eine Prozeß schreibt in die Datei, der andere liest daraus. Die Kommunikation ist auf die Elter-Kind-Gruppe beschränkt. Für global sichtbare Kommunikation sind named pipes vorgesehen. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Signale Problem: Synchrones Warten blockiert Prozesse Abhilfe: Benachrichtigung durch asynchrone Signale (Software-Interrupts) Aufsetzen der Reaktion auf ein Signal, z.B. in UNIX mit sigaction(ISR) Abarbeiten des Hauptprogramms Bei Signaleintritt: Abarbeiten der angegebenen ISR Weiterarbeiten im Hauptprogramm (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Signale Implementierung von Semaphoroperationen mit Signalen TYPE Semaphor = RECORD besetzt : BOOLEAN; frei : SIGNAL; END; PROCEDURE P(VAR S:Semaphor); BEGIN IF S.besetzt THEN waitFor(S.frei) END; S.besetzt:= TRUE; END P; PROCEDURE V(VAR S:Semaphor); S.besetzt:= FALSE; send(S.frei) END V; Unterbrechung verhindern durch Sperren des Signal-Interrupt !? Zusätzlich muß die Semaphore vorher erzeugt werden. Nachteil des Systems ist, daß es nur auf Mono-Prozessorsystemen funktioniert; Auf Multiprozessorsystemen kann durch CPU-Prio-Erhöhung ein Signal nicht verhindert werden. Es sind andere Mechanismen nötig. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: atomic broadcast Problem: Synchronisierung von Globaldaten (Systemtabelle, ...) Lösung: Atomarer Rundspruch (atomic broadcast) Endliche Übertragungszeit Nachricht an alle oder keinen Gleiche Nachrichten-Reihenfolge Implementierung: konsistente Message-Reihenfolge Konsistenz durch Nachrichten an alle, auch sich selbst! Empfänger- prozesse Sender · Globald a ten 1 4 3 mailbox (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation Programmsynchronisation Rendez-vous-Konzept (Ada) Warten ohne Pufferung aufeinander Senderprogramm Empfängerprogramm ... ... send( Empfänger,Msg ) ; receive ( Sender , Msg ) ... ... Beim Rendez-vous-Konzept müssen beide Programme aufeinander warten und verlieren so Zeit. Natürlich läßt sich dies durch Schaffung von besonderen Programmteilen (Threads) entschärfen, falls eine Parallelarbeit möglich ist. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Synchronisation Guarded Commands (Dijkstra 1975) Konstrukte: IF Auswahl IF C1 command1 (a > b) print „größer / gleich“ C2 command2 (a < b) print „kleiner“ .... FI FI DO unendl. loop C1 command1 C2 command2 .... OD (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Synchronisation Kommunizierende Sequentielle Prozesse CSP (Hoare 1978) Konstrukte: s A Auf ein Ereignis s folgt der Zustand A P = (s A) Wenn s kommt, so wird Zustand A erreicht, und P nimmt A an. Für den parallelen Fall ist P = (s1 A | s2 B | ... | sn D) Wenn s1 kommt, nimmt P den Wert A an. Wenn s2 kommt, dann B, usw. (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Synchronisation CSP in OCCAM (INMOS 1988) Konstrukte: Kanal!data1 send(Kanal,data1) Kanal?data2 receive(Kanal,data2) Bei Rendez-vous: data2 := data1 PAR cmd1 parallele Ausführung cmd2 SEQ cmd1 sequentielle Ausführung ALT cmd1 einer davon wird ausgeführt Bei OCCAM werden zuerst Sender und Empfänger synchronisiert, dann die beiden Daten synchronisiert (kopiert). (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Synchronisation Beispiel: Erzeuger – Verbraucher, Code für Puffer Die Abfragen in beiden Strängen des ALT-Statements haben als Guards die log. Bedingung und Synchronisation. Erzeuger und Puffer werden synchronisiert, dann die beiden Datenpuffereinträge synchronisiert (kopiert). Die Flußkontrolle wird durch die Verbrauchernachfrage bewirkt. producer!buffer producer?buffer consumer consumer?more Erzeuger Puffer Verbraucher producer consumer!buffer consumer?buffer consumer!more (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation
Prozeßkommunikation: Synchronisation Synchronisation durch Kommunikation putInBuffer(item) send(consumer,item) Item internen Puffer, geregelt mit P() und V() getFromBuffer(item) receive(producer,item) interner Puffer Item, geregelt mit P() und V() Erzeuger LOOP produce(item); send(consumer ,item); END Verbraucher LOOP receive(producer ,item); consume(item); END (C) Goethe-Universität, Frankfurt R.Brause - Betriebssysteme: ProzeßSynchronisation