• Keine Ergebnisse gefunden

Vorlesung Betriebssysteme I Thema 8: Threads (Aktivitäten, die zweite) Robert Baumgartl 13. Januar 2020

N/A
N/A
Protected

Academic year: 2021

Aktie "Vorlesung Betriebssysteme I Thema 8: Threads (Aktivitäten, die zweite) Robert Baumgartl 13. Januar 2020"

Copied!
22
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Vorlesung Betriebssysteme I

Thema 8: Threads (Aktivitäten, die zweite)

Robert Baumgartl

13. Januar 2020

1 / 22

(2)

Threads (Leichtgewichtsprozesse)

I Prozess = Container für Ressourcen + (ein)

identifizierbarer Handlungsablauf (“Thread of Execution”) I Idee: Trennung beider Konzepte:

I Prozess = Container für Ressourcen (passiv)

I Thread = identifizierbarer unabhängiger Handlungsablauf (aktiv)

I →ein oder mehrere Threads pro Prozess möglich, diese teilen sich die Ressourcen des Prozesses

I →parallele Abarbeitung innerhalb eines Adressraums Der Begriff „Thread“ ist auch im Deutschen weitestgehend etabliert, die korrekte Übersetzung „Faden“ benutzen nur Fanatiker. Eher wird noch „Leichtgewichtsprozess“ eingesetzt.

2 / 22

(3)

Veranschaulichung mehrerer Threads

...... ......

......

P1

......

P3

......

P2 P1

......

Abbildung:Übergang von mehreren Prozessen zu mehreren Threads in einem Prozess

3 / 22

(4)

Konsequenzen

I Thread kann nur innerhalb eines Prozesses existieren!

I alle Threads eines Prozesses teilen sich dessen

Ressourcen und Adressraum bis auf die Register und den Stack

I ⇒kein Schutz zwischen Threads eines Prozesses I Kooperation im Vordergrund

dem Prozess gehörend jedem Thread gehörend Adressraum Program Counter Globale Variablen Register

eröffnete Dateien Stack (!)

Signale automatische Variablen Kindprozesse Globalzustand

Tabelle:Gemeinsame und private Ressourcen von Threads eines Prozesses (Beispiele)

4 / 22

(5)

Warum Threads?

I feingranulare Parallelität der Verarbeitung

I Erzeugung/Vernichtung viel schneller als von Prozessen I effektive Ausnutzung mehrerer CPUs/Kerne

I Umschaltung zwischen Threads eines Prozesses schnell I Dekomposition in Threads liefert Performancegewinn,

insbesondere wenn Ein-/Ausgabe-beschränkte Funktionalität

Abbildung:Textverarbeitung mit 3 Threads (Tanenbaum:Modern Operating Systems, S.95)

5 / 22

(6)

Variante 1: User-Level-Threads

I Threads werden im User Mode (d.h., ohne Intervention und Wissen des Betriebssystems) erzeugt, synchronisiert, vernichtet

I Threadbibliothek, die Routinen zum Erzeugen, Beenden, Synchronisieren und Umschalten von Threads realisiert, erforderlich

I Threadbibliothek übernimmt Management aller Threads (speichert deren Zustandsinformationen)

I Umschaltungvorgang: Sichern und Restaurieren des Thread-Kontextes (alle Register)

I kooperatives Programmiermodell: jeder Thread muss freiwillig (ab und zu) den Prozessor abgeben

I Kernel hat kein Wissen über Threads, kennt (und verwaltet) nur Prozesse

I m:1-Abbildung, d. h. , allen Threads ist genau eine Kernel-Aktivität zugeordnet, nämlich der zugehörige Prozess

6 / 22

(7)

Veranschaulichung von User-Level-Threads

...... ...... ......

......

P1

Thread Library

T1 T2 T3

User Mode Kernel Mode

Abbildung:User-Level-Threads

7 / 22

(8)

User-Level-Threads, cont’d

Bewertung:

+ kann (auch) für Betriebssystem implementiert werden, welches kein Threadkonzept kennt (z. B. MS-DOS) + Threadoperationen besonders schnell, da kein

Kernein-/austritt, kein Flush der Prozessorcaches, kein Adressraumwechsel

– blockierender Systemruf blockiertalleThreads eines Prozesses (verhindert Parallelität), Abhilfe:

? nichtblockierende Systemrufe

? im Vorhinein ermitteln, ob Ruf blockieren wird (z. B. mittels select()); wenn ja, dann Weiterarbeit eines anderen Threads

– Page Faultblockiert alle Threads eines Prozesses – kooperatives Programmiermodell mit freiwilliger Abgabe

des Prozessors erforderlich (da keine unterbrechende Instanz aka Betriebssystem)

8 / 22

(9)

Variante 2: Kernel-Level-Threads

I 1:1-Abbildung (jedem Thread istgenau eineAktivität des Kernels zugeordnet)

I Threads im Kernel verwaltet, dieser verteilt Threads auf alle existierenden Kerne

I Threadoperationen teurer, da mit Systemruf (~eintritt,

~austritt) verbunden (z. B.CreateThread()in Win32) I Kombinationen aus User-Level- und Kernel-Level-Threads

sind ebenfalls möglich

9 / 22

(10)

Veranschaulichung von Kernel-Level-Threads

...... ............ ......

P1

CPU

T1 T2 T3

User Mode Kernel Mode

Abbildung:Kernel-Level-Threads

10 / 22

(11)

Transition single-threaded → multi-threaded

Komplexität der Umwandlung traditioneller sequentieller Programme inmultithreaded applicationsdarf nicht unterschätzt werden!

Einige Problemkreise:

I globale Systemvariablen, wieerrnostehen nur einmal pro Prozess zur Verfügung

I nicht reentranter Code, z. B. in Bibliotheken, muss vor gleichzeitigem Betreten durch mehrere Threads geschützt werden

I Signale sind meist prozessspezifisch

I Management mehrerer Stacks bei User-Level-Threads

11 / 22

(12)

Threads in Windows

I Windows-Welt: beginnend ab Windows NT (Win32-API) sind Kernel-Level-Threads im System verankert.

I CreateProcess()legt einen neuen Adressraum an und startet in ihm einen (ersten) Thread

I mittelsCreateThread()können in einem existierenden Prozess weitere Threads gestartet werden

I User-Level-Threads existierenzusätzlich:die so genanntenFibers

I d. h. , es können mehrere User-Level-Threads (Fibers) in einem Kernel-Level-Thread existieren

12 / 22

(13)

Threads in Linux

I ab Kernel 2.0 BibliothekLinuxThreads

I weitgehend, aber nicht vollständig, POSIX-kompatibel I limitiert (max. Threadanzahl 8192)

I nicht allzu performant

I daher ab 2002 Entwicklung derNative POSIX Thread Library(NPTL)

I behebt diese Nachteile, voll POSIX-kompatibel I 1:1-Implementierung (1 Thread pro Kernelaktivität) I andere Unixe besitzen u. U. andere

Thread-Implementierungen, die aber stets POSIX-Threads realisieren

Abfrage der installierten Thread-Version in Linux:

~> getconf GNU_LIBPTHREAD_VERSION

13 / 22

(14)

POSIX-Threads (Pthreads)

I POSIX standardisiert ein Thread-API für Unix-artige Betriebssysteme

I API wirdPthreadsgenannt

I Standard enthält keine Aussage zur Implementierung der Funktionen (z. B., ob Kernel- oder User-Level-Threads realisiert werden sollen)

I man 7 pthreads

I auch für Win32 verfügbar (pthreads-w32)

14 / 22

(15)

Pthreads-API – Übersicht

pthread_create() Anlegen eines neuen Threads pthread_join() Warten auf Ende des Threads pthread_exit() Beenden des rufenden Threads pthread_detach() Abkoppeln vom Vater

pthread_kill() Zustellung eines Signals an Thread pthread_attr_init() Init der Thread-Attribute

pthread_mutex_lock() pthread_mutex_unlock()

Synchronisation am Mutex

pthread_cond_init() Anlegen einer Bedingungsvariable pthread_cond_wait()

pthread_cond_signal()

Sync. an Bedingungsvariable Tabelle:Einige Funktionen der Pthreads-API

15 / 22

(16)

Pthreads-Programmierung

I #include <pthread.h>

I Linken mit Schalter-lpthread

I Funktionsnamen beginnen stets mitpthread_

I alle Funktionen liefern 0 wenn erfolgreich, -1 bei Fehler I Threads eines Prozesses kommunizieren über

gemeinsame (globale) Variable I IPC nur zu Threads anderer Prozesse

16 / 22

(17)

Hello, world mittels Pthreads

# i n c l u d e < p t h r e a d . h>

# i n c l u d e < s t d i o . h>

# i n c l u d e < s t d l i b . h>

# d e f i n e MAXITER 200000 v o i d ∗t h r e a d _ f (v o i d ∗arg ) {

p r i n t f ("world!\n") ; p t h r e a d _ e x i t ( NULL ) ; }

i n t main (v o i d) {

p t h r e a d _ t a ; i n t r e t ;

p r i n t f ("Hello, ") ; r e t = p t h r e a d _ c r e a t e (

&a , /∗ p o i n t e r t o v a r i a b l e c o n t a i n i n g t h r e a d ID ∗/

NULL , /∗ p o i n t e r t o t h r e a d a t t r i b u t e s ∗/

(v o i d∗) &t h r e a d _ f , / t h r e a d f u n c t i o n ∗/

NULL ) ; /∗ p o i n t e r t o argument ∗/

i f ( r e t ! = 0 ) {

p e r r o r ("creating 1st thread") ; e x i t ( EXIT_FAILURE ) ;

}

p t h r e a d _ j o i n ( a , NULL ) ; e x i t ( EXIT_SUCCESS ) ; }

17 / 22

(18)

Erzeugung eines Threads

int pthread_create(pthread_t *tid, pthread_attr_t

*attr, void* (*start_fkt)(void*), void *arg);

I erzeugt neuen Thread

I *tid: Identifikator des neuen Threads I *attr: legt Attribute des Threads fest I *start\_fkt: Startfunktion

I *arg: Zeiger auf (beliebiges) Datum, welches der Thread als Parameter erhält

I keine Vater-Sohn-Beziehungen; jeder darf create-n und join-en

18 / 22

(19)

Join und Detach

int pthread_join(pthread_t tid, void **ret);

I Analogon zum waitpid(), wartet auf Ende des Threads mit Id tid

I Rückgabewert über ret

I erst nach join() wird der Thread vernichtet (analog Zombie-Status)

int pthread_detach(pthread_t tid);

I macht den Thread un-join-bar, d.h., er wird sofort vernichtet, wenn er seine Startfunktion verlässt

19 / 22

(20)

GNU Portable Threads (GNU Pth)

I User-Level-Threads für Unix I m:1-Implementierung

I http://www.gnu.org/software/pth/

I kooperatives Multitasking mit Prioritäten I Linken mit Schalter-lpth

20 / 22

(21)

Hello, world! mit GNU Pth

# i n c l u d e < p t h . h>

# i n c l u d e < s t d i o . h>

# i n c l u d e < s t d l i b . h>

v o i d ∗p t h _ t h r e a d (v o i d ∗arg ) {

p r i n t f ("world!\n") ; p t h _ e x i t ( NULL ) ; }

i n t main (v o i d) {

p t h _ t t i d ; i f ( ! p t h _ i n i t ( ) ) {

p r i n t f ("No pth lib available\n") ; e x i t ( EXIT_FAILURE ) ;

}

p r i n t f ("Hello, ") ;

t i d = pth_spawn ( PTH_ATTR_DEFAULT, &p t h _ t h r e a d , NULL ) ; i f ( ! t i d ) {

p r i n t f ("Could not spawn thread\n") ; e x i t ( EXIT_FAILURE ) ;

}

p t h _ j o i n ( t i d , NULL ) ; r e t u r n 0 ;

}

21 / 22

(22)

Was haben wir gelernt?

I Threads sind eine Abstraktion zur effizienten Parallelisierung von Programmabläufen.

I Kernel-Level-Threads↔User-Level-Threads I Windows bringt beide Arten „von Haus aus“ mit

I wichtigste Implementierung unter Unix/Linux: Pthreads I pthread_create()startet einen neuen Thread

I pthread_exit()beendet einen Thread (oder: Verlassen der Threadfunktion)

22 / 22

Referenzen

ÄHNLICHE DOKUMENTE

Abbildung: Zwei Funktionen klammern den kritischen Abschnitt Jeder, der auf eine gemeinsam genutzte Variable zugreift, muss diese Funktionen vor bzw.. nach dem

Sollten die zwei Punkte eine Sprechpause andeuten, erwartet der Leser eine weitere Äußerung des Schreibers Lelika, ansonsten erwartet er im weiteren Verlauf eine Reaktion

• Gibt es für einen Puffer genau einen Producer und einen Consumer, weckt das notify() des Consumers (wenn überhaupt, dann) stets den Producer

The basic rule for using mutual exclusion is straightforward: in a multi-threaded program all shared mutable data must be protected by associating it with some mutex, and you

• Funktion blockiert, bis ¨ uber einen Deskriptor readfds, writefds oder exceptfds Daten gelesen oder geschrieben werden k¨ onnen bzw. eine Datei ihren Status

➥ Anmerkung: alle Modelle in diesem Abschnitt gelten in der selben Form auch f ¨ur klassische Prozesse (mit genau einem Thread)... 2.2

Erweitern Sie das Programm so, daß ein zweiter Thread erzeugt wird, der eine Referenz auf dasselbe Objekt erh¨alt. Warten Sie vor dem Ausdrucken der Zahl, bis auch dieser Thread

In this paper, we propose the analysis of a news data stream using article threads, a relevance-based technique that turns the stream of news articles into threads by re- taining