Übungen Betriebssysteme (BS)

U2 – Thread-Synchronisation

Alwin Berger

🚀 by Decker

Prozesse und Fäden

  • Prozess (schwergewichtige Prozesse): Haben eigenen Adressraum
    • pid_t als Datentyp für die Prozess-Identifikation
  • Faden (engl. thread): Teilt sich Adressraum mit schwergew. Prozess
    • Ein Prozess kann mehrere Fäden haben
    • Jeder Faden hat seinen eigenen Stack
    • Heap-, BSS- und Daten-Segment werden geteilt
    • pthreads bietet die in POSIX standardisierte Schnittstelle
    • Jeder Faden hat eine eineindeutige Identifikation (pthread_t)
  • Kettfaden (engl. warp): Nicht atomar-zerlegbarer Zusammenschluss von Fäden (GPU-Programmierung)

Schwergewichtiger Prozess (Skizze)

images/U2/0001.svg

Überschreiben schwergewichtiger Prozesse (Skizze)

images/U2/0002.svg

Schwergewichtiger Prozess vor fork (Skizze)

images/U2/0003.svg

Schwergewichtiger Prozess nach fork (Skizze)

images/U2/0007.svg

Geteilter Speicher mit shmget(2)

images/U2/0008.svg

Prozess vor pthread_create (Skizze)

images/U2/0004.svg

Prozess mit einem Faden (Skizze)

images/U2/0005.svg

Prozess mit zwei Fäden (Skizze)

images/U2/0006.svg

POSIX-Fäden erzeugen und beenden

  • pthread_create(&thread, attr, &f, arg) erzeugt Faden
    • thread ist die Faden-Variable vom Typ pthread_t
    • attr ist ein Zeiger auf den Arbeitsbereich des Fadens
    • f ist die auszuführende Funktion
    • arg ist ein Zeiger auf die Argumente mit der f ausgeführt werden soll
  • Rückgabewerte:
    • =0 bei Erfolg
    • !=0 bei Misserfolg
  • In f: pthread_exit(p): Beendet Faden und liefert Zeiger p zurück

Beispiel eines POSIX-Fadens

images/U2/0011.svg

Faden mit Hauptprozess zusammenführen

  • pthread_join(&thread, &q) legt den aufrufenden Faden/Prozess schlafen, bis der Faden thread terminiert
  • q ist eine Zeigervariable, die mit dem durch pthread_exit(p) zurückgegebenen Zeiger p überschrieben werden soll

POSIX-Fäden vergleichen und Identität feststellen

  • pthread_equal(&thread1, &thread2)
  • liefert einen Wert ungleich 0 zurück, falls es sich um den selben Faden handelt
  • pthread_self() liefert die ID eines Fadens als Rückgabewert

Ein Beispiel mit zwei Fäden

images/U2/0012.svg

Wettlaufsitaution

images/U2/0009.svg

Semaphore

  • Ein Semaphor (σῆμα dt. Zeichen, φέρειν dt. tragen) ist eine Datenstruktur zur Verwaltung beschränkter Ressourcen in digitalen Systemen
  • Analogie: Eisenbahnsignal
images/U2/Semaphor.png

Semaphore

  • Die Semaphor wird als Zähler mit der maximalen Anzahl n der entsprechenden Ressource initialisiert: s := n
  • P(): Prolaag = probeer te verlagen (dt. versuche zu senken)
    • s>0: Ressource wird beansprucht und s := s−1
    • s=0: Warten bis Ressource wieder verfügbar ist: s>0
  • V(): Verhogen bzw. vrijgeven dt. freigeben: s := s+1

Aufgabe

images/U2/0013.svg

Aufgabe

images/U2/0014.svg

Aufgabe

images/U2/0015.svg

Aufgabe

images/U2/0016.svg

Aufgabe

images/U2/0017.svg

Aufgabe

images/U2/0018.svg

Aufgabe

images/U2/0019.svg

POSIX-Semaphore

  • sem_init(&s, 0, x) initialisiert ein Semaphor s mit dem Wert x
  • sem_destroy(&s) zerstört ein Semaphor s
  • sem_getvalue(&s, &v) schreibt Wert des Semaphors s in v
  • P(): sem_wait(&s)
  • V(): sem_post(&s)
  • Rückgabewerte:
    • 0 bei Erfolg
    • ≠ 0 bei Misserfolg

Binäre Semaphore und Schlossvariablen

  • Nimmt ein Semaphor ausschließlich die Werte 0 und 1 an, spricht man von einem binären Semaphor
  • Wird ein binärer Semaphor stets von dem Aktivitätsträger wieder freigegeben der diesen auch gesperrt hat, spricht man von einem gegenseitigen Ausschluss (engl. mutual exclusion bzw. Mutex) bzw. einer Schlossvariablen (Lock)

Initialisieren und zerstören von POSIX-Schlössern

  • pthread_mutex_init(&s, attr) initialisiert Schloss s (ungesperrt)
  • pthread_mutex_destroy(&s) zerstört ein Schloss s
  • const pthread_mutexattr_t* attr ist ein Zeiger auf weitere Attribute und wird meist auf NULL gesetzt
  • Ein POSIX-Schloss s ist vom Typ pthread_mutex_t
  • Rückgabewerte:
    • 0 bei Erfolg
    • ≠ 0 bei Misserfolg

Öffnen und schließen von POSIX-Schlössern

  • pthread_mutex_lock(&s) schließt Schloss s
  • pthread_mutex_unlock(&s) öffnet Schloss s
  • Rückgabewerte:
    • 0 bei Erfolg
    • ≠ 0 bei Misserfolg

Ein Beispiel mit zwei Fäden und einem Schloss

images/U2/0010.svg

Gegenseitiger Ausschluss

images/U2/0020.svg

Gegenseitiger Ausschluss

images/U2/0021.svg

Gegenseitiger Ausschluss

images/U2/0022.svg

Gegenseitiger Ausschluss

images/U2/0023.svg

Gegenseitiger Ausschluss

images/U2/0024.svg

Gegenseitiger Ausschluss

images/U2/0025.svg

Gegenseitiger Ausschluss

images/U2/0026.svg

Exkurs: Mehrkanalspeicher mit Semaphore

images/U2/0027.svg

Exkurs: Semaphore Logik des 7016

images/U2/0028.svg

Was haben wir heute gelernt?

  • Leicht- und schwergewichtige Prozesse
  • Das Erzeugen von Fäden in Linux (POSIX-Thread)
  • Das Zustandekommen einer Wettlaufsitaution
  • Die Verwendung von Synchronisationmittel
    • Semaphor
    • Schloss (Mutex)