Prof. Dr. rer. nat. Roland Wismüller Aufgabenblatt 7 Musterlösung Vorlesung Betriebssysteme I Wintersemester 2017/18 Aufgabe 1: Steuerung eines Warenautomaten (Bearbeitung zu Hause) Anleitung wie man solche Probleme systematisch lösen kann: 1) Identifizieren Sie die Prozesse des Systems Die Prozesse sind die Aktivitäten, die nebenläufig ausgeführt werden und sich dabei synchronisieren müssen. Sie ergeben sich meist unmittelbar aus der Problemstellung. In der Aufgabe haben wir drei Prozesse: Automat, Kunden und Lieferant. 2) Notieren Sie die Aktionen der einzelnen Prozesse Hier muss klar werden, welcher Prozess was tut, in welcher zeitlichen Reihenfolge die Aktionen eines Prozesses ablaufen und wo es Schleifen oder Verzweigungen gibt. Die Aktionen eines Prozesses ergeben sich meist unmittelbar aus der Aufgabenbeschreibung. Die Synchronisationsoperationen (die P- und V-Operationen auf Semaphoren) müssen Sie hier noch nicht einfügen; sie werden in Schritt 5 ergänzt. Die Prozesse laufen wie folgt ab: falls leer: warte auf Lieferant; warte auf 5 Euro; gib Chips-Tüte aus; 3) Identifizieren Sie die Synchronisationsbedingungen warte, bis Automat frei; wirf 5 Ein-Euro-Stücke ein; warte auf Chips-Tüte; gib Automaten frei; fülle Chips-Tüten nach; Eine Synchronisationsbedingung ist eine zeitliche Abhängigkeit, die zwischen zwei oder mehr Prozessen durchgesetzt werden muss. Die Synchronisationsbedingungen ergeben sich am besten dadurch, dass man die Problembeschreibung genau durchliest und jede zeitliche Bedingung mit einer eigenen Farbe in dem Text markiert wird. In der Aufgabe gibt es vier Synchronisationsbedingungen: (i) Nur ein Kunde benutzt den Automaten gleichzeitig (wechselseitiger Ausschluss). (ii) Ein Kunde wartet, bis der Automat die Ware liefert. (iii) Der Automat wartet, bis 5 Euro eingeworfen wurden. (iv) Der leere Automat wartet, bis der Lieferant 200 Chips-Tüten gebracht hat. 4) Definieren Sie die Semaphore Im Normalfall muss jede der Synchronisationsbedingungen mit einem eigenen Semaphor realisiert werden. Geben Sie jeweils an, wie das Semaphor heißen soll, wie es initialisiert wird und welcher Bedingung es zugeordnet ist. (i) mutex = 1: zum wechselseitigen Ausschluss der Kunden. (ii) ware = 0: zur Blockierung des Kunden bis zur Warenübergabe. (iii) geld = 0: zur Blockierung des Automaten bis zur Geldübergabe. (iv) chips = 200: zur Blockierung des Automaten, falls er leer ist. 1
5) Ergänzen Sie die Prozesse aus Schritt 2 durch die Semaphor-Operationen Jetzt müssen Sie die P- und V-Operationen der Semaphore, die in Schritt 4 eingeführt wurden, in die Prozesse aus Schritt 2 einfügen. P-Operationen müssen dabei an die Stellen gesetzt werden, an denen ein Prozess auf ein bestimmtes Ereignis warten muss (also ggf. blockiert werden soll). V-Operationen kommen an die Stellen, an denen ein Prozess einem anderen signalisiert, dass er jetzt weiterlaufen darf. Eine erste Lösung sieht daher wie folgt aus: Semaphore ware = 0; Semaphore geld = 0; Semaphore chips = 200; int i; int count=200; // falls leer: warte auf Lieferant; P(chips); // warte auf 5 Euro; P(geld); //gib Chips-Tüte aus; count ; V(ware); // warte, bis Automat frei; P(mutex); // wirf 5 Ein-Euro-Stücke ein; V(geld); // warte auf Chips-Tüte; P(ware); // gib Automaten frei; V(mutex); //fülle Chips-Tüten nach; for (i=count; i<200; i++) V(chips); count = 200; Da wir in der Vorlesung davon ausgehen, daß der Zählerwert eines Semaphors nicht ausgelesen werden kann 1, brauchen wir einen zusätzlichen Zähler count, der die Chipstüten im Automaten mitzählt. Achtung: Die obige Lösung hat noch eine mögliche Race-Condition beim Zugriff auf count! Um dieses Problem zu lösen, müssen wir für einen wechselseitigen Ausschluss zwischen Automat und Lieferant sorgen, der sicherstellt, daß count immer identisch mit dem Zähler des Semaphors chips ist. Dazu verwenden wir ein Semaphore mutex2, das mit 1 initialisiert wird. Semaphore mutex2 = 1; Semaphore ware = 0; Semaphore geld = 0; Semaphore chips = 200; int i; int count=200; P(mutex2); // falls leer: warte auf Lieferant; P(chips); // warte auf 5 Euro; P(geld); //gib Chips-Tüte aus; count ; V(ware); V(mutex2); Anmerkungen: // warte, bis Automat frei; P(mutex); // wirf 5 Ein-Euro-Stücke ein; V(geld); // warte auf Chips-Tüte; P(ware); // gib Automaten frei; V(mutex); //fülle Chips-Tüten nach; P(mutex2); for (i=count; i<200; i++) V(chips); count = 200; V(mutex2); In der Klausur müssen Sie nur die Ergebnisse der Schritte 4 und 5 hinschreiben, es sei denn, es wird ausdrücklich anders verlangt. 1 Reale Implementierungen lassen dies ggf. zu. 2
In der Klausur werden derart komplexe Synchronisationsaufgaben nicht verlangt. Aufgabe 2: Leser-Schreiber Synchronisation (Bearbeitung zu Hause) Gemeinsame Variable: Semaphore oktowrite = 1; Semaphore readers = 3; int activereaders = 0; Schreiber: oktowrite.p(); // write data base oktowrite.v(); Leser: readers.p(); mutex.p(); activereaders++; if (activereaders == 1) oktowrite.p(); mutex.v(); // read data base readers.v(); mutex.p( ; activereaders--; if (activereaders == 0) oktowrite.v(); mutex.v(); Aufgabe 3: Leser-Schreiber Synchronisation (Bearbeitung zu Hause) monitor ReaderWriter boolean writerisactive; integer activereaders; condition oktoaccess; (* Initialisierung *) writerisactive := false; activereaders := 0; procedure ReadStart while writerisactive do wait(oktoaccess); activereaders := activereaders + 1; procedure ReadEnd activereaders := activereaders - 1; if activereaders = 0 then signal(oktoaccess); procedure WriteStart 3
while writerisactive or activereaders > 0 do wait(oktoaccess); writerisactive := true; procedure WriteStop writerisactive := false; signal(oktoaccess); end monitor; Aufgabe 4: Synchronisation mit Monitoren (Bearbeitung zu Hause) monitor Toilette integer nfrau; (* Zahl der Frauen in der Toilette *) integer nmann; (* Zahl der Männer in der Toilette *) condition okfrau; (* Frau kann eintreten *) condition okmann; (* Mann kann eintreten *) (* Initialisierung *) nfrau := 0; nmann := 0; procedure Frau_moechte_eintreten while nmann > 0 do wait(okfrau); nfrau := nfrau + 1; procedure Frau_verlaesst_die_Toilette nfrau := nfrau - 1; if nfrau = 0 then signal(okmann); procedure Mann_moechte_eintreten while nfrau > 0 do wait(okmann); nmann := nmann + 1; procedure Mann_verlaesst_die_Toilette nmann := nmann - 1; if nmann = 0 then signal(okfrau); end monitor; Aufgabe 5: Synchronisation: Implementierung eines Semaphors (Bearbeitung zu Hause) public class MySemaphore private int sem; 4
private final Lock m1; private final Condition c1; public MySemaphore(int initval) sem = initval; m1 = new Lock("m1"); c1 = m1.newcondition("c1"); public void acquire() m1.lock(); while (sem == 0) c1.await(); sem--; m1.unlock(); public void release() m1.lock(); sem++; c1.signal(); m1.unlock(); 5