01.03.2014 Aufrufe

Prozesse und Threads

Prozesse und Threads

Prozesse und Threads

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Kapitel 2<br />

<strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong><br />

2.1 <strong>Prozesse</strong><br />

2.2 <strong>Threads</strong><br />

2.3 Interprozesskommunikation<br />

2.4 Klassische Probleme der Interprozesskommunikation<br />

2.5 Scheduling


<strong>Prozesse</strong><br />

Das Prozessmodell<br />

Unterschied Prozess / Programm<br />

Prozess ist eine Aktivität<br />

Besteht aus Programm, Input, Output <strong>und</strong> Zustand<br />

a) Multiprogramming von vier Programmen<br />

b) Konzeptionelles Modell von vier unabhängigen sequentiellen <strong>Prozesse</strong>n<br />

c) Zu einem Zeitpunkt ist nur ein Programm aktiv.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 2


<strong>Prozesse</strong>rzeugung<br />

• OS muss sicherstellen, dass alle wichtigen <strong>Prozesse</strong><br />

existieren.<br />

• Manchmal: alle <strong>Prozesse</strong> die jemals benötigt werden,<br />

werden beim Startup erzeugt<br />

• Im allgemeinen: Möglichkeit zur Erzeugung / Beendigung<br />

erforderlich<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 3


<strong>Prozesse</strong>rzeugung<br />

Ereignisse, die die Erzeugung eines <strong>Prozesse</strong>s auslösen<br />

1. Initialisierung des Systems (boot)<br />

2. Systemaufruf zum Erzeugen eines <strong>Prozesse</strong>s durch einen<br />

anderen Prozess<br />

3. Benutzeranfrage, einen neuen Prozess zu erzeugen<br />

4. Start eines Batch Jobs<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 4


<strong>Prozesse</strong>rzeugung<br />

Booten<br />

Mehrere <strong>Prozesse</strong> werden gestartet<br />

• <strong>Prozesse</strong> zur Interaktion mit Anwender<br />

• <strong>Prozesse</strong> für bestimmte Funktionen<br />

– Email-service<br />

– Drucker-Warteschlange<br />

– Firewall<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 5


Windows Taskmanager<br />

Prozessliste<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 6


Prozessbeendigung<br />

Bedingungen, die zum Beenden von <strong>Prozesse</strong>n führen<br />

1. Normales Beenden (freiwillig)<br />

2. Beenden auf Gr<strong>und</strong> eines Fehlers (freiwillig)<br />

3. Beenden auf Gr<strong>und</strong> eines schwerwiegenden<br />

Fehlers(unfreiwillig)<br />

4. Beenden durch einen anderen Prozess (unfreiwillig)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 7


Prozesshierarchien<br />

• Elternprozess erzeugt Kindprozess. Kindprozess kann weitere<br />

<strong>Prozesse</strong> erzeugen. In UNIX ist das eine Prozessfamilie<br />

• Unter Windows gibt es kein Konzept einer Prozesshierarchie,<br />

alle <strong>Prozesse</strong> sind gleichwertig.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 8


Prozesszustände (1)<br />

1. Prozess blockiert wegen<br />

Eingabe<br />

2. Schedular wählt einen<br />

anderen Prozess<br />

3. Schedular wählt diesen<br />

Prozess<br />

4. Eingabe vorhanden<br />

• Mögliche Prozesszustände<br />

– rechnend (running)<br />

– blockiert (blocked)<br />

– rechenbereit (ready)<br />

• Es existieren die dargestellten Übergänge zwischen diesen<br />

Zuständen<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 9


Prozesszustände (2)<br />

• Die unterste Schicht eines prozessstrukturierten Betriebssystems<br />

behandelt Interrupts <strong>und</strong> Scheduling<br />

• Oberhalb befinden sich sequentielle <strong>Prozesse</strong><br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 10


Implementierung von <strong>Prozesse</strong>n<br />

Einige Felder eines typischen<br />

Eintrags einer Prozesstabelle<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 11


Umschalten zwischen <strong>Prozesse</strong>n<br />

Context Switch<br />

Aufgaben der untersten Schicht des Betriebssystems bei<br />

Auftreten einer Unterbrechung<br />

1. Hardware sichert Befehlszähler etc<br />

2. Hardware holt neuen Befehlszähler vom Interruptvektor<br />

3. Assemblerfunktion speichert Register<br />

4. Assemblerfunktion erzeugt neuen Stack<br />

5. C-Unterbrechungsroutine läuft (puffert Ein/- Ausgaben)<br />

6. Schedular sucht nächsten Prozess<br />

7. C-Funktion kommt zur Assemblerfunktion zurück<br />

8. Assemblerfunktion startet neuen aktuellen Prozess<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 12


Schritte für den Systemaufruf<br />

Adresse<br />

0xFFFFFFFF<br />

Return zum Aufrufer<br />

Systemaufruf in den Kern<br />

5. Put code for read in register<br />

Bibliotheksprogramm<br />

read<br />

4.<br />

10.<br />

Benutzerraum<br />

11. Erhöhe Stackpointer<br />

6.<br />

Rufe read auf<br />

3. Push fd<br />

Benutzerprogramm<br />

ruft read auf<br />

count = read (fd,<br />

buffer, nbytes<br />

2. Push &buffer<br />

1. Push nbytes<br />

9.<br />

fd : filedescriptor<br />

buffer : Ziel<br />

nbytes : Länge<br />

Kernadressraum<br />

Verteilung<br />

7. 8.<br />

Systemaufrufbehandlung<br />

13


<strong>Threads</strong><br />

Das Threadmodell (1)<br />

• Traditionelles Modell:<br />

Prozess hat<br />

• einen Adressraum<br />

• einen Ausführungsfaden<br />

• Manchmal ist es<br />

wünschenswert, mehrere<br />

Ausführungsfäden zu haben<br />

Drei <strong>Prozesse</strong> mit jeweils einem Thread<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 14


<strong>Threads</strong><br />

Das Threadmodell (2)<br />

• Traditionelles Modell: Prozess hat<br />

• einen Adressraum<br />

• einen Ausführungsfaden<br />

• Manchmal ist es wünschenswert,<br />

mehrere Ausführungsfäden zu<br />

haben<br />

• wie eigene <strong>Prozesse</strong>, aber<br />

gemeinsamer Adressraum<br />

Ein Prozess mit drei <strong>Threads</strong><br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 15


Das Threadmodell (3)<br />

1. Spalte: Elemente werden zwischen den <strong>Threads</strong> eines<br />

<strong>Prozesse</strong>s aufgeteilt<br />

2. Spalte: Thread-eigene Elemente<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 16


Das Threadmodell (3)<br />

Jeder Thread hat seinen eigenen Stack<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 17


Einsatz von <strong>Threads</strong> (1)<br />

Ein Textprogramm mit drei <strong>Threads</strong><br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 18


Einsatz von <strong>Threads</strong> (2)<br />

Dienstag, 30. April<br />

2013<br />

Ein Web-Server mit mehreren <strong>Threads</strong><br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 19


Einsatz von <strong>Threads</strong> (3)<br />

• Grober Auszug des Codes zur vorherigen Folie.<br />

(a) Dispatcher thread<br />

(b) Worker thread<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 20


Einsatz von <strong>Threads</strong> (4)<br />

Drei Möglichkeiten, einen Server zu bauen:<br />

Modell<br />

<strong>Threads</strong><br />

<strong>Prozesse</strong> (ein Thread)<br />

Endlicher Automat<br />

Eigenschaften<br />

Parallel, blockierende Systemdienste<br />

Nicht parallel, blockierende<br />

Systemdienste<br />

Parallel, nicht blockierende<br />

Systemdienste<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 21


Einsatz von <strong>Threads</strong> (5)<br />

Was <strong>Threads</strong> zu bieten haben:<br />

• Sie ermöglichen es, das Konzept von sequenziellen <strong>Prozesse</strong>n,<br />

die blockierende Systemaufrufe (z.B. für Platten E/A) machen,<br />

beizubehalten <strong>und</strong> troztdem Parallelität zu erzielen<br />

• Blockierende Systemaufrufe vereinfachen die Programmierung<br />

<strong>und</strong> die Parallelität verbessert die Performance<br />

• Der Einzel-Thread-Server behält die Einfachheit von<br />

blockierenden Systemaufrufen bei, gibt jedoch die Performance<br />

auf.<br />

• Der dritte Ansatz bringt hohe Performance durch Parallelität,<br />

benutzt aber nicht blockierende Aufrufe <strong>und</strong> ist deshalb<br />

schwieriger zu programmieren<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 22


Realisierung von <strong>Threads</strong> im<br />

Benutzeradressraum (1)<br />

Ein Benutzer-Level<br />

Thread Paket<br />

Vorteile:<br />

• kann auch auf Betriebssystemen<br />

realisiert werden, die <strong>Threads</strong> nicht<br />

unterstützen<br />

• Umschalten zwischen <strong>Threads</strong> geht<br />

vergleichsweise schnell<br />

Run-time system –<br />

Laufzeitsystem, enthält eine<br />

Sammlung von Prozeduren,<br />

die auch <strong>Threads</strong> verwalten<br />

(thread_create, thread_exit,...)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 23


Realisierung von <strong>Threads</strong> im<br />

Benutzeradressraum (2)<br />

Ein Benutzer-Level<br />

Thread Paket<br />

Dienstag, 30. April<br />

2013<br />

Probleme:<br />

• Ruft ein Thread einen blockierenden<br />

Systemaufruf auf (z.B. read von<br />

Tastatur), werden alle Thread blockiert<br />

• Systemaufrufe müssten nicht<br />

blockierend implementiert werden <strong>und</strong><br />

Anwendungsprogramme müssten dafür<br />

modifiziert werden (sehr aufwendig)<br />

• Seitenfehler eines <strong>Threads</strong> blockieren<br />

ebenso alle <strong>Threads</strong><br />

• Startet ein Thread, kommt kein<br />

anderer an die Reihe, bis der erste von<br />

sich aus die CPU freigibt<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 24


Realisierung von <strong>Threads</strong> im Kern(1)<br />

Ein Thread Paket,<br />

verwaltet vom Kern<br />

Kern hat Thread-Tabelle, die<br />

alle <strong>Threads</strong> im System<br />

verwaltet<br />

Zur Sicherheit: Exkurs über<br />

Betriebssystemkern!<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 25


Betriebssystemkern (1)<br />

Wikipedia: Ein Betriebssystemkern oder Systemkern (engl. kernel<br />

) ist der zentrale Bestandteil eines Betriebssystems. In ihm ist die<br />

Prozess- <strong>und</strong> Datenorganisation festgelegt, auf der alle weiteren<br />

Softwarebestandteile des Betriebssystems aufbauen. Er ist meist in<br />

der untersten Softwareschicht, hat also Zugriff auf die Hardware.<br />

Die Konstruktion eines Betriebssystemkerns gehört zum<br />

Themenbereich der Informatik <strong>und</strong> des Softwareengineerings.<br />

Gängige Anforderungen an einen Systemkern sind<br />

Parallelverarbeitung verschiedener Aufgaben (Multitasking),<br />

Einhaltung zeitkritischer Grenzen, Offenheit für unterschiedlichste<br />

Anwendungen <strong>und</strong> Erweiterungen.<br />

Nicht zum Systemkern gehörende Teile werden als Userland<br />

bezeichnet.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 26


Betriebssystemkern (2)<br />

Bestandteile<br />

Ein Systemkern ist in Schichten (oder Layer, siehe Schichtenmodell) aufgebaut,<br />

wobei die unteren (maschinennahen) Schichten die Basis für die darüberliegenden<br />

bilden. Die oberen Schichten können Funktionen der unteren Schichten aufrufen,<br />

aber nicht umgekehrt.<br />

Folgende Schichten sind vorhanden (von unten nach oben):<br />

• Schnittstelle zur Hardware (Geräte, Speicher, Prozessoren)<br />

• Speicherverwaltung (evtl. einschließlich virtuellem Hauptspeicher)<br />

• Prozessverwaltung (auch Scheduler genannt)<br />

• Geräteverwaltung (auch Device Management genannt)<br />

• Dateisysteme<br />

Wenn alle diese Funktionen im Systemkern selbst integriert sind, spricht man von<br />

einem monolithischen Kernel. Bei einem Mikrokernel finden wesentliche Teile in<br />

getrennten <strong>Prozesse</strong>n statt. Daneben, bzw. zwischen den beiden liegend, gibt es<br />

noch den sogenannten Makrokernel.<br />

Auf jeden Fall außerhalb des Kernels laufen die Anwenderprozesse, die sich der<br />

vom Kernel angebotenen Funktionen bedienen, um mit der Maschine zu<br />

kommunizieren.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 27


Betriebssystemkern (3)<br />

Aufgaben eines Kernels :<br />

• Schnittstelle zu Anwenderprogrammen (Starten, Beenden, Ein-/Ausgabe,<br />

Speicherzugriff)<br />

•Kontrolle des Zugriffs auf Prozessor, Geräte, Speicher (Scheduler, Gerätetreiber,<br />

Speicherschutz). Möglichst alleiniger Zugriff des Kernels auf diese Ressourcen.<br />

•Verteilung der Ressourcen, etwa der Prozessorzeit(en) (bzw. der Prozessoren) auf<br />

die Anwenderprogramme<br />

•Strukturierung der Ressourcen, etwa Abbildung von Dateisystemen auf<br />

blockorientierte Geräte wie Festplatten, Netzwerkprotokoll-Stack auf<br />

Netzwerkkarten.<br />

•Auflösung von Zugriffskonflikten, etwa Verriegelung bei Mehrprozessorsystemen,<br />

Warteschlangen bei knappen Ressourcen<br />

•Virtualisierung der Ressourcen (Prozessor: <strong>Prozesse</strong>, Festplatte: Dateien,<br />

Netzwerkkarte: z. B. Sockets, Speicher: virtueller Speicher, Geräte: Spezialdateien)<br />

•Überwachung von Zugriffsrechten auf Dateien <strong>und</strong> Geräte bei<br />

Mehrbenutzersystemen<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 28


Betriebssystemkern (4)<br />

Schichten eines Unix Betriebssystems<br />

User<br />

Interface<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 29


Betriebssystemkern (5)<br />

Kernel Mode – User Mode<br />

Kernel <strong>und</strong> user space sind<br />

unterschiedliche Teile des<br />

Adressraumes. User space ist<br />

reservierter Bereich für<br />

applikationen (jede einen eigenen<br />

Bereich).<br />

Kernel space ist auch ein reservierter Bereich, jedoch nur einer<br />

für alle Anwendungen, die dort nicht schreiben können. Nur das<br />

Betriebssystem kann den Prozessor auf kernel mode umschalten<br />

<strong>und</strong> auf diesen Bereich zugreifen... Anwendungen laufen<br />

dagegen normalerweise nur im user mode des prozessors, <strong>und</strong><br />

verwenden damit einen eingeschränkten Befehlssatz ist.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 30


Dienstag, 30. April<br />

2013<br />

Betriebssystemkern (6)<br />

CPU- Betriebsarten: Kernel Mode – User Mode<br />

Das Programmstatuswort der<br />

CPU enthält die aktuelle<br />

Betriebsart: kernel mode, user<br />

mode Damit wird ein<br />

Schutzsystem realisiert<br />

kernel mode: - privilegierte Betriebsart (nur für Betriebssystem)<br />

- alle Instruktionen sind erlaubt, inbes. IO auf Hardware<br />

user mode:- nicht privilegierte Betriebsart<br />

- nicht alle Instruktionen sind erlaubt (z.B. Zugriff auf Ein-/Ausgabe)<br />

- nicht alle Register dürfen verändert werden (z.B. Register für<br />

Speicherkonfiguration)<br />

Umschaltung in Kernmodus: mittels Interrupt (über SW oder HW ausgelöst)<br />

Umschaltung in Benutzermodus: mittels Maschinenbefehl bzw. PSW-<br />

Modifikation<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 31


Realisierung von <strong>Threads</strong> im Kern(2)<br />

Ein Thread Paket,<br />

verwaltet vom Kern<br />

Kern hat Thread-Tabelle, die alle<br />

<strong>Threads</strong> im System verwaltet<br />

Thread-Tabelle enthält<br />

Informationen über Register,<br />

Zustand... der einzelnen <strong>Threads</strong><br />

Alle Aufrufe, die blockieren können,<br />

sind als Systemaufrufe realisiert mit<br />

höheren Kosten als Aufrufe im<br />

Laufzeitsystem – aber:<br />

wenn ein Thread blockiert, hat der<br />

Kern die Möglichkeit, einen anderen<br />

(prozesseigegnen oder fremden)<br />

Thread zu starten<br />

Fazit: flexibel, aber teuer<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 32


Hybride Implementierung<br />

Multiplexen von Benutzer-Level-<strong>Threads</strong> in Kern-<strong>Threads</strong><br />

= Versuch, die Vorteile beider Implementierungen zu<br />

verbinden<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 33


Scheduler Activations<br />

• Ziel: – Verbindung der Funktionalität von Kern-<strong>Threads</strong> mit der Performance<br />

von Benutzeradressraum <strong>Threads</strong><br />

• Vermeiden von unnötigen user/kernel Umschaltungen<br />

• Kern ordnet jedem Prozess virtuelle Prozessoren zu <strong>und</strong> veranlasst das<br />

Laufzeitsystem (im Benutzeradressraum) den Prozessoren <strong>Threads</strong> zuzuordnen<br />

(geht auch bei Multiprozessorsystemen)<br />

• Gr<strong>und</strong>idee: Wenn der Kern weiss, dass ein Thread durch einen blockierenden<br />

Systemaufruf oder Seitenfehler blockiert hat, benachrichtigt er das<br />

Laufzeitsystem (Upcall) Das Laufzeitsystem kann seine <strong>Threads</strong> darauf hin neu<br />

schedulen, also den gegenwärtigen Thread als blockiert markieren <strong>und</strong> einen<br />

anderen starten<br />

• Problem: F<strong>und</strong>amental reliance on kernel (lower layer) calling procedures in<br />

user space (higher layer)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 34


Pop-Up <strong>Threads</strong><br />

Erzeugen eines neuen <strong>Threads</strong>, wenn eine Nachricht eintrifft<br />

(a) bevor die Nachricht eintrifft<br />

(b) nachdem die Nachricht eintrifft<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 35


Multithreading<br />

• Üblich: zuerst nur ein Thread<br />

• Startet weitere threads(z.B. thread_create (proc_name))<br />

• Manchmal hierarchisch, manchmal flach<br />

• Wenn thread fertig: thread_exit<br />

• Warten auf thread-Ende: thread_wait<br />

• CPU freiwillig hergeben: thread_yield<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 36


Posix Thread Beispiel – 1<br />

Main 1<br />

PROGRAM For<strong>Threads</strong><br />

!<br />

! Funktionsbeschreibung:<br />

! Thread Testprogramm<br />

!<br />

! Programm kreiert <strong>und</strong> startet mehrere <strong>Threads</strong>:<br />

! - Worker wird mehrmals kreiert (Master-Worker) <strong>und</strong> gestartet.<br />

! Diese Workerthreads arbeiten periodisch mit Hilfe eines Timers.<br />

! Sie stoßen wiederum alle den selben Thread an<br />

! - Thread2 ist der mittels pthread_cond_signal von Worker ange-<br />

! stossene Thread, der in einer Endlosschleife mit pthread_cond_wait<br />

! auf Aufträge wartet. Er muss vom Hauptprogramm mit pthread_cancel<br />

! explizit beendet werden<br />

! - Thread3 läuft als unabhängiger Thread <strong>und</strong> führt eine Anzahl Ite-<br />

! rationen aus. Für ihn werden Scheduling-Parameter (Priorität)<br />

! gesetzt.<br />

! - Das Programm endet erst, wenn alle <strong>Threads</strong> abgearbeitet oder beendet sind.<br />

! Geprüft wird dies mit pthread_join.<br />

!<br />

!<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 37


Posix Thread Beispiel – 2<br />

benutzte Posix Funktionen<br />

! Functions:<br />

! pthread_cond_init Conditionvariable erzeugen <strong>und</strong> mit<br />

! Defaultwert initialisieren<br />

! pthread_cond_broadcast Alle Thread, die auf eine bestimmte<br />

! Condition-Variable hören, benachrichtigen<br />

! pthread_cond_signal Einen Thread, der auf eine bestimmte<br />

! Condition-Variable hört, benachrichtigen<br />

! pthread_create Einen Thread erzeugen<br />

! pthread_join Synchronisieren mehrerer <strong>Threads</strong><br />

! pthread_mutex_init Mutexvariable erzeugen <strong>und</strong> mit<br />

! Defaultwert initialisieren<br />

! pthread_mutex_lock Mutex locken vor broadcast<br />

! pthread_mutex_unlock Mutex unlocken nach broadcast<br />

! pthread_setschedparam Scheduling Verfahren <strong>und</strong> Priorität<br />

! für einen Thread festlegen<br />

!<br />

!D-<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 38


Posix Thread Beispiel – 3<br />

Datendeklaration<br />

INCLUDE 'GEN_INCL:ST(P<strong>Threads</strong>)'<br />

EXTERNAL Test_Thread1<br />

EXTERNAL TestF_Thread2<br />

EXTERNAL Test_Thread3<br />

PARAMETER PTHREAD_MUTEX_DEFAULT = 0<br />

PARAMETER anzworkers = 4<br />

INTEGER *4 ThrCount , SchedNr<br />

INTEGER *4 INDX , IStatus<br />

INTEGER *4 ThreadStackSize /819200/<br />

!size_t<br />

INTEGER *4 exitval<br />

RECORD /pthread_mutex_t/ SlowMutex, WeckMutex, CountMutex,<br />

RECORD /pthread_cond_t/ WeckCond, CountCond<br />

COMMON /COM_<strong>Threads</strong>/ SlowMutex, WeckMutex, CountMutex, WeckCond,<br />

1 CountCond, ThrCount<br />

REAL *4 x /1.0/<br />

RECORD /pthread_t/ Worker (anzworkers)<br />

RECORD /pthread_t/ Thread2<br />

RECORD /pthread_t/ Thread3<br />

RECORD /pthread_attr_t/s_gl_pthread_attr<br />

RECORD /pthread_attr_t/s_gl_pthread_attr2<br />

RECORD /sched_param/schedparam<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 39


Posix Thread Beispiel – 4<br />

<strong>Threads</strong> erzeugen<br />

ThrCount = 0<br />

schedparam.sched_priority = 9 !PRI_FG_MIN_NP 8 - 15!<br />

CALL pthread_mutex_init(CountMutex,%VAL(PTHREAD_MUTEX_DEFAULT))<br />

CALL pthread_mutex_init(WeckMutex,%VAL(PTHREAD_MUTEX_DEFAULT))<br />

! Thread Condition Varibale initialisieren<br />

IStatus = pthread_cond_init(WeckCond, )<br />

IStatus = pthread_cond_init(CountCond,)<br />

IStatus = pthread_attr_init(s_gl_pthread_attr)<br />

IStatus = pthread_attr_init(s_gl_pthread_attr2)<br />

IStatus = pthread_attr_setstacksize(s_gl_pthread_attr, ThreadStackSize)<br />

IStatus = pthread_attr_setstacksize(s_gl_pthread_attr2, ThreadStackSize)<br />

DO INDX = 1,anzworkers<br />

! Eine Prozedur mehrmals als Thread erzeugen (anzworkers)<br />

IStatus = pthread_create(Worker(INDX), %VAL(PTHREAD_CREATE_JOINABLE),<br />

1 test_thread1, %VAL(Indx))<br />

ENDDO<br />

IStatus = pthread_create(Thread2, %VAL(PTHREAD_CREATE_JOINABLE), test_thread2, %VAL(anzworker+1))<br />

IStatus = pthread_create(Thread3, %VAL(PTHREAD_CREATE_JOINABLE), test_thread3, %VAL(anzworker+2))<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 40


Posix Thread Beispiel – 5<br />

benachrichten <strong>und</strong> beenden<br />

!<br />

! Prioritäten der <strong>Threads</strong> festlegen<br />

!<br />

IStatus = pthread_setschedparam (%VAL(Thread3.Pointer), %VAL(Sched_Other), schedparam)<br />

!<br />

! Mittels Broadcast alle <strong>Threads</strong> der Variante Worker wecken<br />

!<br />

IStatus = pthread_cond_broadcast (%REF(WeckCond))<br />

PRINT*,'alle <strong>Threads</strong> aktiviert, Main wartet noch auf Rückmeldung '<br />

!<br />

! Mittels Signal Thread2 wecken<br />

!<br />

IStatus = pthread_cond_signal(%REF(CountCond))<br />

!<br />

! Ende aller <strong>Threads</strong> abwarten/oder herbeiführen<br />

!<br />

DO INDX = 1, anzworkers<br />

IStatus = pthread_join32(%VAL(Worker(INDX).Pointer),exitval)<br />

ENDDO<br />

IStatus = pthread_join32(%VAL(Thread3.Pointer),exitval)<br />

IStatus = pthread_cancel (%VAL(Thread2.Pointer))<br />

IStatus = pthread_join32(%VAL(Thread2.Pointer),exitval)<br />

END<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 41


Posix Thread Beispiel – 6<br />

test_Thread1,arbeitet periodisch, terminiert selbst<br />

SUBROUTINE test_thread1(thrnum)<br />

IMPLICIT NONE<br />

!<br />

! Thread wird mehrfach (Anzahl= anzworkers), konkurrierend in MAIN erzeugt<br />

! <strong>und</strong> mittels Broadcast geweckt.<br />

!<br />

! Verwendete Prozeduren:<br />

!<br />

! pthread_cond_wait Warten auf Ereignis <strong>und</strong> aufwachen des <strong>Threads</strong> mit Mutex<br />

! pthread_cond_timedwait Warten auf Ereignis mit Timeout (verwendbar als Timer bei <strong>Threads</strong>)<br />

! pthread_get_expiration_np Bestimmung der Ablaufzeit des Timers indem zur Systemzeit ein<br />

! Delta in Sek<strong>und</strong>en addiert wird<br />

! pthread_mutex_lock WeckMutex locken für pthreadcond_wait<br />

!<br />

INCLUDE 'GEN_INCL:ST(P<strong>Threads</strong>)'<br />

INTEGER<br />

*4 ThrCount<br />

RECORD<br />

/pthread_mutex_t/ SlowMutex<br />

RECORD<br />

/pthread_mutex_t/ WeckMutex<br />

RECORD<br />

/pthread_mutex_t/ CountMutex<br />

RECORD<br />

/pthread_cond_t/ WeckCond<br />

RECORD<br />

/pthread_cond_t/ CountCond<br />

COMMON /COM_<strong>Threads</strong>/ SlowMutex, WeckMutex, CountMutex, WeckCond,<br />

1 CountCond, ThrCount<br />

CHARACTER * 8 CTime<br />

INTEGER *4 a , thrnum, Error, INDX /0/, IStatus<br />

RECORD /PThread_TimeSpec_T/ WaitTime, ResWaitTime<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 42


Posix Thread Beispiel – 7<br />

test_Thread1,arbeitet periodisch, terminiert selbst<br />

CALL TIME (CTime)<br />

a = %LOC(thrnum)<br />

PRINT *, a,%LOC(a), ' thread ',a,' gestartet um:',CTime,%LOC(CTime), %LOC(WaitTime.tv_sec)<br />

WaitTime.tv_sec = 4<br />

WaitTime.tv_nsec = 0<br />

! Synchronisierung der <strong>Threads</strong> mit dem Hauptprogramm mittels einer<br />

! Condition Variablen<br />

IStatus = pthread_mutex_lock(WeckMutex)<br />

IStatus = pthread_cond_wait(WeckCond, WeckMutex)<br />

IStatus = pthread_mutex_unlock (WeckMutex)<br />

!<br />

! Timer definieren<br />

!<br />

IStatus = pthread_get_expiration_np (%REF(waittime),%REF(reswaittime))<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 43


Posix Thread Beispiel – 8<br />

test_Thread1,arbeitet periodisch, terminiert selbst<br />

DO INDX = 1,4<br />

IStatus = pthread_mutex_lock(CountMutex)<br />

thrCount = thrCount + 1<br />

IStatus = pthread_mutex_unlock(CountMutex)<br />

IStatus = pthread_mutex_lock (WeckMutex)<br />

IStatus = pthread_cond_timedwait(WeckCond, WeckMutex, reswaittime)<br />

Error = pthread_mutex_unlock (WeckMutex)<br />

CALL TIME (CTime)<br />

IF (IStatus .EQ. 0)THEN<br />

PRINT*,a,%LOC(a),' ', IStatus,' über Mutex/Condition rausgekommen'<br />

ELSEIF (IStatus .EQ. ETIMEDOUT) THEN<br />

PRINT*,a,%LOC(a),' Timer abgelaufen thread ',a,' Lauf:',INDX,' ',CTime<br />

ELSE<br />

PRINT*,a,%LOC(a),' Ende von Condition Wait Lauf ',INDX,' um',CTime,' Fehler ', IStatus<br />

ENDIF<br />

IStatus = pthread_get_expiration_np (%REF(waittime),%REF(reswaittime))<br />

IStatus = pthread_cond_signal(CountCond) ! Signal an einen anderen Thread, einen anderen Thread anstoßen<br />

ENDDO<br />

PRINT*,a,%LOC(a), ' Fertig....thread',a<br />

RETURN<br />

END<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 44


Posix Thread Beispiel – 9<br />

Endlos Thread, wird von main gestoppt<br />

SUBROUTINE test_thread2(thrnum)<br />

IMPLICIT NONE<br />

!<br />

! Endlos-Thread sitzt in ConditionWait <strong>und</strong> wird von anderen <strong>Threads</strong><br />

! via SIGNAL geweckt um dann irgendeinen Unsinn zu machen<br />

! Zusätzlich: Sperren <strong>und</strong> Freigeben einer globalen Variablen mittels<br />

! Mutex Lock <strong>und</strong> Unlock<br />

! Beenden des Endlos-<strong>Threads</strong> via PTHREAD_CANCEL in MAIN<br />

!<br />

! Verwendete Prozeduren:<br />

!<br />

! pthread_mutex_init Initialisierung der Mutexvariablen<br />

! für pthread_cond_wait<br />

! pthread_cond_wait Aufwachen des <strong>Threads</strong> mit Mutex<br />

! pthread_mutex_lock WeckMutex locken für pthread_cond_wait<br />

! pthread_mutex_unlock WeckMutex freigeben nach<br />

! pthread_cond_wait<br />

INCLUDE 'GEN_INCL:ST(P<strong>Threads</strong>)'<br />

INTEGER<br />

*4 ThrCount<br />

RECORD<br />

/pthread_mutex_t/ SlowMutex<br />

RECORD<br />

/pthread_mutex_t/ WeckMutex<br />

RECORD<br />

/pthread_mutex_t/ CountMutex<br />

RECORD<br />

/pthread_cond_t/ WeckCond<br />

RECORD<br />

/pthread_cond_t/ CountCond<br />

COMMON /COM_<strong>Threads</strong>/ SlowMutex, WeckMutex, CountMutex, WeckCond,<br />

1 CountCond, ThrCount<br />

RECORD<br />

Dienstag, 30. April<br />

2013<br />

/pthread_mutex_t/ WaitMutex<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 45


Posix Thread Beispiel – 10<br />

Endlos Thread, wird von main gestoppt<br />

CHARACTER * 8 CTime<br />

REAL *4 count /3.0/, x, y<br />

INTEGER *4 a, thrnum, I, IStatus<br />

IStatus = pthread_mutex_init(WaitMutex,)<br />

a = %LOC(thrnum)<br />

IStatus = 0<br />

DO WHILE (IStatus .EQ. 0)<br />

x = SIN(count)<br />

Count = Count + 1<br />

CALL Time (CTime)<br />

IStatus = pthread_mutex_lock(WaitMutex)<br />

IStatus = pthread_cond_wait(CountCond, WaitMutex)<br />

IStatus = pthread_mutex_unlock(WaitMutex)<br />

! Bereich der globalen Variablen thrcount schuetzen<br />

IStatus = pthread_mutex_lock(CountMutex)<br />

thrCount = INT(Count) + 1<br />

DO I =2,3<br />

y = y+(y*(i+1)/(i-1))<br />

ENDDO<br />

PRINT*,a,' y in Thread Typ 2',y<br />

PRINT*,a,' Absolute Anzahl in Thread Typ 2 ',thrcount<br />

IStatus = pthread_mutex_unlock(CountMutex)<br />

ENDDO<br />

RETURN<br />

END<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 46


Posix Thread Beispiel – 11<br />

test_thread3 - 1<br />

SUBROUTINE test_thread3 (thrnum)<br />

IMPLICIT NONE<br />

!<br />

! Thread wird in MAIN gestartet <strong>und</strong> führt Berechnungen mit<br />

! vielen Iterationsschritten durch. Getestet (demontriert) wird die<br />

! Prioriätssteuerung (Scheduling) dieses <strong>Threads</strong> im Verhältnis<br />

! zu den konkurrierenden <strong>Threads</strong>.<br />

!<br />

INCLUDE 'GEN_INCL:ST(P<strong>Threads</strong>)'<br />

LOGICAL *4 Thread_Hold<br />

INTEGER<br />

*4 ThrCount<br />

RECORD<br />

/pthread_mutex_t/ SlowMutex<br />

RECORD<br />

/pthread_mutex_t/ WeckMutex<br />

RECORD<br />

/pthread_mutex_t/ CountMutex<br />

RECORD<br />

/pthread_cond_t/ WeckCond<br />

RECORD<br />

/pthread_cond_t/ CountCond<br />

COMMON /COM_<strong>Threads</strong>/ SlowMutex, WeckMutex, CountMutex, WeckCond,<br />

1 CountCond, ThrCount<br />

CHARACTER *8 CTime<br />

REAL *4 x<br />

REAL *4 y /1.0/<br />

INTEGER<br />

*4 a<br />

INTEGER *4 count1 /1/<br />

INTEGER *4 count /3/<br />

INTEGER<br />

*4 I<br />

INTEGER<br />

*4 thrnum<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 47


Posix Thread Beispiel – 12<br />

test_thread3 - 2<br />

a = %LOC(thrnum)<br />

CALL TIME (CTime)<br />

PRINT *, a,' thread ',a,' gestartet um:',CTime<br />

DO count = 1, 999999<br />

y = 1.0<br />

x = sin(float(count))<br />

DO I =3, 5<br />

y = y+(y*(i+1)/(i))<br />

ENDDO<br />

IF(MOD (count,10000) .EQ. 0) THEN<br />

PRINT*,a,' x = sin(float(count))',x,' count ',count<br />

PRINT*,a,' y in Thread Typ 3 ',y<br />

ENDIF<br />

ENDDO<br />

PRINT*,a,' y in Thread Typ 3 ',y<br />

PRINT*,a,' Fertig!..thread ',a<br />

RETURN<br />

END<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 48


Singlethread-Programme multithreadfähig<br />

machen (1)<br />

Konflikte zwischen <strong>Threads</strong> beim Gebrauch globaler Variablen<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 49


Singlethread-Programme multithreadfähig<br />

machen (2)<br />

<strong>Threads</strong> können private globale Variablen haben<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 50


Interprozesskommunikation IPC<br />

• Weil <strong>Prozesse</strong> vom Betriebssystem gegenseitig von<br />

einander geschützt werden (Speicherschutz !), braucht<br />

man eine Interprozesskommunikationen, falls <strong>Prozesse</strong><br />

untereinander kommunizieren, aufeinander warten oder<br />

Daten <strong>und</strong> Ressourcen austauschen müssen.<br />

• Typische Fälle dafür sind:<br />

– Mehrere <strong>Prozesse</strong> müssen spezielle Daten gemeinsam verwenden.<br />

– Die <strong>Prozesse</strong> sind untereinander abhängig <strong>und</strong> müssen aufeinander<br />

warten.<br />

– Daten müssen von einem Prozess zu einem anderen weitergereicht<br />

werden.<br />

– Die Verwendung von Systemressourcen muss koordiniert werden<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 51


IPC – Techniken unter Linux<br />

Entnommen dem openbook von Galileo unter:<br />

http://openbook.galileocomputing.de/linux_unix_programmierung/Kap09-<br />

000.htm#RxxKap09000040002B71F02D10D<br />

• Namenlose Pipes<br />

• Benannte Pipes (FIFO Pipes)<br />

• Message Queue (Nachrichtenspeicher)<br />

• Semaphore<br />

• Shared Memory (gemeinsamer Speicher)<br />

• STREAMS<br />

• Sockets<br />

• Lock Files (Sperrdateien)<br />

• Datei Sperren (Record Locking)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 52


IPC – Techniken unter Linux<br />

Namenlose Pipes<br />

• Pipes, wie auch FIFOs (named Pipes), sind die einzigen<br />

beiden IPCs, die garantiert auf jedem System vorhanden<br />

sind.<br />

• Eine Pipe ist ein unidirektionaler Kommunikationskanal<br />

zwischen zwei verwandten <strong>Prozesse</strong>n<br />

• $ ps ax | less startet in der Shell zwei <strong>Prozesse</strong>. Einer führt das<br />

Kommando ps ax aus <strong>und</strong> schreibt das Ergebnis an die<br />

Standardausgabe. Durch die Pipe (|) wird allerdings diese<br />

Standardausgabe an den Prozess less weitergeleitet. less liest hierbei<br />

die Daten von der Standardeingabe ein <strong>und</strong> gibt aus, was ihm das<br />

Kommando ps durch die Pipe zuschickt<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 53


IPC – Techniken unter Linux -Pipes<br />

• Wenn Daten in beide Richtungen ausgetauscht werden,<br />

muss eine zweite Pipe dazu verwendet werden. Eine Pipe ist<br />

wie ein Rohr, wo Daten in die eine Seite (Prozess A)<br />

hineingesteckt werden <strong>und</strong> bei Prozess B wieder<br />

herauskommen.<br />

• Eine Pipe dient außer zur Kommunikation zwischen zwei<br />

<strong>Prozesse</strong>n zur Flusskontrolle, weil eine Pipe nur eine<br />

bestimmte Menge an Daten aufnehmen kann. Ist die Pipe<br />

voll, wird ein Prozess mindestens so lange angehalten, bis<br />

mindestens ein Byte aus der vollen Pipe gelesen wurde <strong>und</strong><br />

Platz vorhanden ist, um die Pipe wieder mit Daten zu<br />

befüllen. Andersherum: ist die Pipe leer, wird der lesende<br />

Prozess so lange angehalten, bis der schreibende Prozess<br />

etwas in diese Pipe schickt.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 54


IPC – Techniken unter Linux -Pipes<br />

• Es gibt also eine Schreibseite <strong>und</strong> eine Leseseite bei einer<br />

Pipe. Somit ist also nur eine Kommunikation in einer<br />

Richtung möglich (half-duplex):<br />

Eigenschaften von elementaren E/A-Funktionen bei Pipes<br />

• read() – liest Daten vom Ende des Puffers der Pipe, entweder<br />

– synchron (blockierend), bis sich genügend Daten in der Pipe befinden. Schreibt kein Prozess in<br />

die Pipe, blockiert read() so lange, bis der schreibende Prozess den Systemaufruf close() aufruft.<br />

Dieses Blockieren von read() eignet sich zum Synchronisieren von <strong>Prozesse</strong>n.<br />

oder<br />

– asynchron (nicht blockierend) , indem mit der Funktion fcntl() das Flag O_NONBLOCK oder<br />

O_NDELAY gesetzt wird. Ist die Pipe fürs Schreiben geöffnet worden, aber momentan leer,<br />

liefert read() 0 (nicht EOF) zurück<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 55


IPC – Techniken unter Linux -Pipes<br />

• write() schreibt die Daten immer ans Ende des Pipe-Puffers, entweder .<br />

– synchron (blockierend): Ist die Pipe voll, wird der schreibende Prozess so lange blockiert, bis<br />

wieder genügend Platz zum Schreiben vorhanden ist<br />

oder<br />

– asynchron (nicht blockierend), indem mit der Funktion fcntl() das Flag O_NONBLOCK oder<br />

O_NDELAY gesetzt wird. Bei vollem Puffer liefert der schreibende Prozess 0 zurück..<br />

• Meistens betreibt man eine Pipe blockierend. Ein Schreiben innerhalb der<br />

PIPE_BUF-Grenze ist atomar, kein anderer Prozess kann dieses Schreiben<br />

unterbrechen <strong>und</strong> selbst in die Pipe schreiben. Versucht ein Prozess, in eine Pipe<br />

zu schreiben, die noch von keinem anderen Prozess zum Lesen geöffnet wurde,<br />

wird dem Prozess das Signal SIGPIPE (broken pipe) gesendet, was standardmäßig<br />

den Abbruch des schreibenden <strong>Prozesse</strong>s bedeutet.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 56


IPC – Techniken unter Linux<br />

Benannte Pipes<br />

• Mit Pipes können nur miteinander verwandte <strong>Prozesse</strong> (fork())<br />

kommunizieren. Mit FIFOs (benannten Pipes) kann man mit einem<br />

völlig fremden Prozess kommunizieren, da solche Pipes über einen<br />

Dateinamen angesprochen werden können.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 57


IPC – Techniken unter Linux<br />

Benannte Pipes - ein Beispiel<br />

• Auf der Shell lässt sich ein FIFO folgendermaßen erstellen:<br />

• $ mkfifo fifo1 Bei einem Blick ins aktuelle Arbeitsverzeichnis finden Sie das FIFO unter<br />

folgendem Eintrag:<br />

• $ ls -l prw-r--r-- 1 tot users 0 2003–12–07 10:53 fifo1<br />

• Am p am Anfang erkennen Sie das FIFO. Sie könnten jetzt etwas in das FIFO schreiben:<br />

• [tty1]<br />

• $ echo Der erste Eintrag in das FIFO > fifo1<br />

• [tty2]<br />

• $ echo Der zweite Eintrag in das FIFO > fifo1<br />

• Beide Dialogstationen blockieren im Augenblick <strong>und</strong> warten, bis die Daten im FIFO<br />

ausgelesen werden. Wir öffnen eine dritte Konsole <strong>und</strong> lesen ihn aus:<br />

• [tty3]<br />

• $ cat fifo1<br />

• Der zweite Eintrag in das FIFO<br />

• Der erste Eintrag in das FIFO<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 58


IPC – Techniken unter Linux<br />

Benannte Pipes - Kommunikationsmodell eines FIFO (First<br />

In - First Out)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 59


IPC – Techniken unter Linux<br />

Message Queue (Nachrichtenspeicher) ist ein<br />

Mechanismus zum Austausch von Nachrichten zwischen<br />

<strong>Prozesse</strong>n. Die Nachrichten werden dabei von einem Prozess<br />

an einen Speicher (der Message Queue = Nachrichtenschlange)<br />

geschickt <strong>und</strong> können dort von einem anderen<br />

Prozess abgeholt werden.<br />

• Größe <strong>und</strong> Anzahl der Nachrichten werden vom System festgelegt.<br />

• Die Nachricht selbst besteht aus einem Text <strong>und</strong> einem Nachrichtentyp.<br />

• Die Nachrichten werden in der Reihenfolge, in der diese eintreffen, auch<br />

wieder ausgelesen.<br />

• Fordert ein Prozess eine Nachricht an, so kann über eine Option angegeben<br />

werden, dass dieser entweder so lange angehalten wird, bis eine Nachricht<br />

eingeht, oder sofort zur Programmausführung zurückkehrt <strong>und</strong> eventuell einen<br />

Fehlercode ausgibt.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 60


IPC – Techniken unter Linux<br />

Message Queue<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 61


IPC – Techniken unter Linux<br />

Shared Memory<br />

• Mehrere <strong>Prozesse</strong> können auf einen gemeinsamen<br />

Datenspeicherbereich zugreifen.<br />

1. Ein Prozess muss diesen gemeinsamen Datenspeicher anlegen.<br />

2. <strong>Prozesse</strong>, die ebenfalls darauf zugreifen sollen, werden mit diesem<br />

Datenspeicher bekannt gemacht, indem der Speicherbereich im Adressraum<br />

der entsprechenden <strong>Prozesse</strong> eingefügt wird. Ebenfalls muss hierbei den<br />

<strong>Prozesse</strong>n mitgeteilt werden, wie diese auf den Speicherbereich zugreifen<br />

können (lesend/schreibend).<br />

• Leider wurde mit dem Shared Memory IPC keine explizite<br />

Synchronisation zur Verfügung gestellt, weshalb man<br />

diese Kontrolle selbst noch mit z. B. Sperren oder<br />

Semaphoren herstellen muss.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 62


IPC – Techniken unter Linux<br />

Sockets<br />

• Sockets wurden im Berkeley-UNIX-System (BSD) als<br />

Kommunikation zwischen <strong>Prozesse</strong>n auf verschiedenen<br />

Rechnern über ein Netzwerk eingeführt. Sockets können<br />

zur Kommunikation verschiedenste Protokolle benutzen, z.<br />

B. TCP/IP, UDP/IP oder UNIX Domain Sockets.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 63


Interprozess Kommunikation IPC<br />

Race Conditions – Wettlaufsituationen<br />

Was passiert, wenn zwei <strong>Prozesse</strong> auf gemeinsam genutzten<br />

Speicher gleichzeitig zugreifen wollen? Beispiel<br />

Druckerspooler<br />

Prozess A liest in = 7<br />

A wird unterbrochen<br />

Prozess B liest in = 7<br />

B trägt Dateinamen an<br />

Stelle 7 <strong>und</strong> aktualisiert<br />

in auf 8<br />

A wird aktiviert <strong>und</strong> trägt<br />

ebenfalls den<br />

Dateinamen auf Stelle 7.<br />

Datei von B wird nicht<br />

gedruckt<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 64


IPC - Race Conditions –Wettlaufsituationen<br />

• Situationen, in denen zwei oder mehr <strong>Prozesse</strong> einen<br />

gemeinsamen Speicher lesen oder beschreiben <strong>und</strong> das<br />

Endergebnis davon abhängt, wer wann genau läuft,<br />

werden Race Conditions genannt.<br />

• Programme, die Race Conditions enthalten, zu<br />

debuggen, macht keinen Spaß, weil Abläufe nicht<br />

reproduzierbar sind. Sie müssen vermieden werden!<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 65


IPC - Kritische Abschnitte (1)<br />

Die Teile des Programms, in denen auf gemeinsam<br />

genutzten Speicher (Resourcen) zugegriffen wird,<br />

nennt man kritische Region oder kritischer Abschnitt<br />

• Keine zwei <strong>Prozesse</strong> dürfen gleichzeitig in ihren<br />

kritischen Bereichen sein<br />

• Es dürfen keine Annahmen über Anzahl <strong>und</strong><br />

Geschwindigkeiten von CPUs gemacht werden<br />

• Kein Prozess, der außerhalb seines kritischen Bereichs<br />

läuft, darf andere <strong>Prozesse</strong> blockieren<br />

• Kein Prozess sollte ewig darauf warten müssen, in seine<br />

kritische Region einzutreten<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 66


IPC - Kritische Abschnitte (2)<br />

• Wechselseitiger Ausschluss (Mutual exclusion) unter<br />

Verwendung von kritischen Regionen<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 67


IPC - Wechselseitiger Ausschluss durch aktives<br />

Warten - Unterbrechungen ausschalten<br />

Einfachste Möglichkeit:<br />

jeder Prozess kann die Interruptbehandlung im Prozessor<br />

ausschalten, wenn er in seinen kritischen Bereich eintritt.<br />

-> Schedular kann Prozess nicht unterbrechen – keine<br />

Raceconditions - Problem gelöst !<br />

Aber: Was ist , wenn der Prozess nachher die Interruptbehandlung<br />

nicht wieder aktiviert?<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 68


IPC - Wechselseitiger Ausschluss durch<br />

aktives Warten - Variablen sperren<br />

Softwarelösung:<br />

es wird eine gemeinsame Sperrvariable (SV) beutzt. Ist SV 0, darf<br />

ein Prozess den Bereich betreten, zuvor setzt er SV 1.<br />

Notwendige Schritte:<br />

1. SV aus dem Speicher laden<br />

2. SV auf null testen<br />

3. wenn nicht, weiter bei 1.<br />

4. SV auf 1 setzten<br />

5. kritischen Bereich betreten<br />

Angenommen, SV = 0. Was passiert, wenn der Scedular P1 im<br />

Schritt 2 unterbricht <strong>und</strong> P2 mit Schritt eins beginnt ?<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 69


IPC - Wechselseitiger Ausschluss durch<br />

aktives Warten - Strikter Wechsel<br />

(a) Process 0. (b) Process 1.<br />

a betritt, wenn turn = 0 b betritt, wenn turn = 1<br />

"Kein Prozess, der außerhalb seines kritischen Bereichs<br />

läuft, darf andere <strong>Prozesse</strong> blockieren" kann hier<br />

verletzt werden !<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 70


IPC - Wechselseitiger Ausschluss durch<br />

aktives Warten - Petersons Lösung<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 71


IPC - Wechselseitiger Ausschluss durch<br />

aktives Warten - Petersons Lösung<br />

Angenommen, beide <strong>Prozesse</strong> rufen enter_region beinahe<br />

gleichzeitig auf:<br />

Beide speichern ihre Prozessnummern in turn<br />

Wer zuletzt kam gewinnt. Das erste Ergebnis geht verloren.<br />

z.B. turn = 1: Wenn beide <strong>Prozesse</strong> zur while Schleife kommen,<br />

führt sie Prozess 0 null mal aus <strong>und</strong> betritt die kritische Region.<br />

Prozess 1 geht in die Schleife <strong>und</strong> betritt seine kritische Region so<br />

lange nicht, bis Prozess 0 seine kritische Region verlässt.<br />

Petersons Lösung für wechselseitigen<br />

Ausschluss<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 72


IPC - Wechselseitiger Ausschluss durch<br />

aktives Warten - TSL Anweisung<br />

Eintreten <strong>und</strong> Verlassen der kritischen Region unter<br />

Verwendung der TSL Anweisung<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 73


IPC - Wechselseitiger Ausschluss durch<br />

aktives Warten - Nachteile<br />

Nachteile des aktiven Wartens:<br />

• Warten verbraucht CPU Zeit<br />

• Ist ein Process mit sehr hoher Priorität in enter_region, kommt er aus der<br />

while Schleife nicht mehr heraus, wenn ein Prozess mit sehr niedriger<br />

Priorität in leave_region einfach nie dran kommt<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 74


IPC - Sleep and Wakeup Erzeuger-<br />

Verbraucher Problem<br />

Zwei <strong>Prozesse</strong> benutzen einen<br />

gemeisamen allgemeinen Puffer<br />

mit fester Größe. Der Erzeuger<br />

legt Informationen hinein, der<br />

Verbraucher nimmt sie heraus.<br />

Synchronisation ist notwendig<br />

bei Aufruf von sleep blockiert<br />

der Schedular den thread<br />

nach Aufruf von wakeup setzt<br />

ihn der Schedular wieder auf<br />

laufbereit<br />

Dienstag, 30. April<br />

2013<br />

Erzeuger-Verbraucher Problem<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 75


IPC - Sleep and Wakeup - Ermitteln Sie die<br />

Race Condition !<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 76


IPC-Sleep and Wakeup –Race Condition<br />

Beispiel:<br />

1. Puffer ist leer<br />

2. consumer hat gerade count gelesen<br />

(= = 0) <strong>und</strong> will sleep aufrufen.<br />

3. Schedular unterbricht consumer<br />

4. Schedular startet producer<br />

5. producer fügt Nachricht ein, erhöht<br />

count um 1<br />

6. producer merkt, dass count = 1 ist<br />

<strong>und</strong> weckt den consumer, der<br />

offensichtlich schlafen muss.<br />

consumer schläft aber noch gar<br />

nicht, Weckruf geht verloren.<br />

7. Schedular startet wieder consumer<br />

8. consumer prüft den count, den er<br />

vorher gelesen hat (==0) <strong>und</strong> geht<br />

schlafen<br />

9. Irgendwann erzeugt der producer<br />

neuen Eintrag <strong>und</strong> geht auch<br />

Problem ist nur, dass ein Wecksignal verloren gehen kann! schlafen.<br />

Dienstag, 30. April<br />

Betriebssysteme <strong>und</strong> nebenläufige 10. Jetzt schlafen beide für immer !<br />

2013<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 77


IPC - Semaphoren : Erzeuger-Verbraucher Problem<br />

‣ Die down Operation eines<br />

Semaphors prüft, ob der Wert<br />

größer 0 ist.<br />

‣ S > 0, down erniedrigt den<br />

Wert um eins (z.B. um einen<br />

gespeicherten Weckruf zu<br />

verbrauchen) <strong>und</strong> macht<br />

einfach weiter<br />

‣ S = 0, Prozess oder Thread<br />

wird sofort schlafen gelegt<br />

‣ down ist atomare (nicht<br />

unterbrechbare) Operation <strong>und</strong><br />

verhindert deshalb Race Conditions<br />

‣ up <strong>und</strong> down werden in der Regel<br />

als Systemaufrufe realisiert, bei<br />

denen das BS alle Unterbrechungen<br />

ausschaltet, solange es die<br />

Semaphore überprüft, sie<br />

aktualisiert <strong>und</strong> den Prozess ggf.<br />

schlafen legt<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 78


IPC Semaphoren : Erzeuger-Verbraucher Problem<br />

‣ Die up Operation erhöht den Wert<br />

um eins<br />

‣ gibt es schlafende <strong>Prozesse</strong> ( in der<br />

Operation down) wird einer von<br />

ihnen geweckt, dekrementiert das<br />

Semaphore wieder auf 0 <strong>und</strong><br />

kommt aus dem down zurück.<br />

‣ Somit bleibt nach einem up an ein<br />

Semaphore, auf das schlafende<br />

<strong>Prozesse</strong> warten, der Wert des<br />

Semaphores immer noch auf 0, aber<br />

es gibt einen Prozess weniger, der<br />

wegen des Semaphores schläft.<br />

‣ up ist ebenfalls eine atomare<br />

Operation<br />

.<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 79


IPC - Semaphoren<br />

‣ Die Mutex Semaphoren werden für<br />

gegenseitigen Ausschluss verwendet.<br />

‣ Sie schützen den Puffer vor<br />

gleichzeitigem Lesen <strong>und</strong> Schreiben.<br />

‣ Full <strong>und</strong> empty sind Synchronisationssemaphoren.<br />

‣ Empty hält den producer an, wenn der<br />

Puffer voll ist.<br />

‣ Full hält den Verbraucher an, wenn der<br />

Puffer leer ist<br />

‣ kein wechselseitiger Ausschluss !<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 80


IPC - Mutexes<br />

Realisierung von mutex_lock <strong>und</strong> mutex_unlock<br />

‣ vereinfachte Semaphore (kann nicht zählen, binäre Semaphore)<br />

‣ dient dem gegenseitigen Ausschluss, Schutz für kritischen Bereich<br />

‣ Ähnlich wie Folie Wechselseitiger Ausschluss durch aktives Warten (5) aber:<br />

thread_yield gibt die CPU wieder frei, kein aktives Warten<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 81


IPC - Probleme mit Semaphoren<br />

Dienstag, 30. April<br />

2013<br />

Angenommen im Code des producer steht:<br />

down (&mutex);<br />

down (&empty);<br />

insert_item(item);<br />

...<br />

Angenommen: der consumer läuft nicht<br />

dann: producer betritt 100 mal den<br />

kritischen Bereich, dekrementiert empty<br />

auf null <strong>und</strong> geht deshalb im kritischen<br />

Bereich schlafen.<br />

Jetzt kommt der consumer <strong>und</strong> kann den<br />

kritischen Bereich nicht betreten, legt sich<br />

auch schlafen<br />

Producer wartet auf up(&empty) des<br />

consumers <strong>und</strong> der consumer wartet auf<br />

up(&mutex) des producers.<br />

Klassischer Fall eines Deadlock<br />

Programmierfehler können leicht passieren<br />

Deshalb Monitore!<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 82


IPC - Monitor (1)<br />

‣ Realisiert ein höherstufiges Synchronisationsprinzip<br />

als Semaphore<br />

‣ Ist eine Sammlung von Prozeduren, Variablen <strong>und</strong><br />

Datenstrukturen.<br />

‣ Prozeduren können aufgerufen, deren Variablen<br />

aber nicht von außen geändert werden<br />

‣ Definitionsgemäß darf <strong>und</strong> kann immer nur ein<br />

Prozess im Monitor aktiv sein<br />

‣ Monitor ist ein Programmiersprachenkonstrukt, das<br />

der Compiler speziell behandlen kann<br />

‣ Der Compiler (nicht der Programmierer) realisiert<br />

den wechselseitigen Ausschluß<br />

Beispiel eines Monitors in Pidgin Pascal<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 83


IPC - Monitor (2)<br />

• Outline of producer-consumer problem with monitors<br />

only one monitor procedure active at one time, buffer has N slots<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 84


IPC - Monitors (3)<br />

Solution to producer-consumer problem in Java (part 1)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 85


IPC - Monitors (4)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 86


IPC – Möglichkeiten<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 87


Message Passing<br />

The producer-consumer problem with N messages<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 88


Barriers<br />

• Use of a barrier<br />

– processes approaching a barrier<br />

– all processes but one blocked at barrier<br />

– last process arrives, all are let through<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 89


Dining Philosophers (1)<br />

• Philosophers eat/think<br />

• Eating needs 2 forks<br />

• Pick one fork at a time<br />

• How to prevent deadlock<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 90


Dining Philosophers (2)<br />

A nonsolution to the dining philosophers problem<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 91


Dining Philosophers (3)<br />

Dienstag, 30. April<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Solution 2013 to dining Anwendugen philosophers - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> problem (part 1) 92


Dining Philosophers (4)<br />

Dienstag, 30. April<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Solution 2013 to dining Anwendugen philosophers - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> problem (part 2) 93


The Readers and Writers Problem<br />

A solution to the readers and writers problem<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 94


The Sleeping Barber Problem (1)<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 95


The Sleeping Barber Problem (2)<br />

Dienstag, 30. April<br />

2013<br />

Solution to sleeping barber problem.<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 96


Scheduling<br />

Introduction to Scheduling (1)<br />

• Bursts of CPU usage alternate with periods of I/O wait<br />

– a CPU-bo<strong>und</strong> process<br />

– an I/O bo<strong>und</strong> process<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 97


Introduction to Scheduling (2)<br />

Dienstag, 30. April<br />

2013<br />

Scheduling Algorithm Goals<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 98


Scheduling in Batch Systems (1)<br />

An example of shortest job first scheduling<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 99


Scheduling in Batch Systems (2)<br />

Dienstag, 30. April<br />

2013<br />

Three level scheduling<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 100


Scheduling in Interactive Systems (1)<br />

• Ro<strong>und</strong> Robin Scheduling<br />

– list of runnable processes<br />

– list of runnable processes after B uses up its quantum<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 101


Scheduling in Interactive Systems (2)<br />

A scheduling algorithm with four priority classes<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 102


Scheduling in Real-Time Systems<br />

Schedulable real-time system<br />

• Given<br />

– m periodic events<br />

– event i occurs within period P i and requires C i<br />

seconds<br />

• Then the load can only be handled if<br />

Dienstag, 30. April<br />

2013<br />

m<br />

<br />

i1<br />

C<br />

i<br />

P<br />

i<br />

<br />

1<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 103


Policy versus Mechanism<br />

• Separate what is allowed to be done with<br />

how it is done<br />

– a process knows which of its children threads<br />

are important and need priority<br />

• Scheduling algorithm parameterized<br />

– mechanism in the kernel<br />

• Parameters filled in by user processes<br />

– policy set by user process<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 104


Thread Scheduling (1)<br />

Possible scheduling of user-level threads<br />

• 50-msec process quantum<br />

• threads run 5 msec/CPU burst<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 105


Thread Scheduling (2)<br />

Possible scheduling of kernel-level threads<br />

• 50-msec process quantum<br />

• threads run 5 msec/CPU burst<br />

Dienstag, 30. April<br />

2013<br />

Betriebssysteme <strong>und</strong> nebenläufige<br />

Anwendugen - <strong>Prozesse</strong> <strong>und</strong> <strong>Threads</strong> 106

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!