01.03.2014 Aufrufe

Prozesse und Threads

Prozesse und Threads

Prozesse und Threads

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

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!