Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Institut für Angewandte Mikroelektronik und Datentechnik Fachbereich Elektrotechnik und Informationstechnik, Universität Rostock Vorlesung Echtzeitbetriebssysteme.

Ähnliche Präsentationen


Präsentation zum Thema: "Institut für Angewandte Mikroelektronik und Datentechnik Fachbereich Elektrotechnik und Informationstechnik, Universität Rostock Vorlesung Echtzeitbetriebssysteme."—  Präsentation transkript:

1 Institut für Angewandte Mikroelektronik und Datentechnik Fachbereich Elektrotechnik und Informationstechnik, Universität Rostock Vorlesung Echtzeitbetriebssysteme VI. Posix Übung Dr.-Ing. Frank Golatowski

2 Institut MD Universität Rostock Ziele der Vorlesung Erzeugung von Threads Diskussion von Synchronisationsproblemen Anwendung von: –Semaphoren –Mutex –Condition Variablen

3 Institut MD Universität Rostock Prozesse vs. Threads Kein Speicherschutz innerhalb eines Prozesses Kommunikation mit anderen Prozessen nur über Betriebssystem oder Shared Memory

4 Institut MD Universität Rostock Thread erzeugen pthread_create(thread_id, attr, func, args) pthread_t pthread_self() –Aufruf gibt den eigenen Thread-ID zurück pthread_yield(); –informiert den Scheduler, dass der Thread sein Zeitquantum abbrechen will. pthread_exit(status) pthread_join(pthread_id) pthread_detach() –Die Exit-Struktur des Threads wird nicht weiter benötigt, durch nachfolgenden pthread_join- Aufrufe. pthread_t me; me = pthread_self(); pthread_t thread; pthread_detach(thread);

5 Institut MD Universität Rostock pthread_create Benötigt vier Argumente –Threadvariable für den Thread –Threadattribute –Startadresse für den Thread –Ein Argument für den Thread pthread_tthread_id; pthread_attr_t attr; void thread_function (void *argument); char *some_arguments pthread_create(thread_id, attr, func, args)

6 Institut MD Universität Rostock Thread Attribute Festlegen von Eigenschaften des Threads in Struktur pthread_attr_t –Stacksize –Priorität –Schedulingverhalten Eigenschaften werden grundsätzlich über Funktionen gesetzt. Initialisierung der Attribut-Struktur vor Benutzung unbedingt erforderlich Beispiel: pthread_attrattr; pthreadthread; pthread_attr_init(&attr); pthread_attr_setcpu_np(&attr, 0); pthread_attr_setschedpolicy( &attr, SCHED_RR); pthread_attr_setstacksize(&attr, 20000); pthread_create(&thread, &attr, function, 0 );

7 Institut MD Universität Rostock Hello world void print_message_function( void *ptr ); main() { pthread_t thread1, thread2; char *message1 = "Hello"; char *message2 = "World"; pthread_create( &thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); exit(0); } void print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); }

8 Institut MD Universität Rostock Aufgaben Entwickeln Sie ein Programm Hello World, das zwei Threads erzeugt. Der erste Thread soll die Ausgabe Hello und der zweite die Ausgabe World machen. Experimentieren Sie mit unterschiedlichen Ausschriften, z.B. –Calling thread: Ich habe gerade 2 Threads erzeugt! –Thread 1: Ich bin Thread 1 und habe die Aufgabe, die Ausgabe Hello zu machen Starten Sie das Programm mehrmals! Nutzen Sie die Online-Dokumentation im Verzeichnis /home/bj74/vorlesung/bs/help!

9 Institut MD Universität Rostock Diskussion des vorherigen Beispiels Ist die Reihenfolge der Ausschriften gesichert? Hat die Länge der Ausschriften Einfluss auf das Verhalten? Was passiert, wenn der erzeugenden Thread sich vor den Threads mit exit(0) beendet. Welches sind die zwei Wettlaufbedingungen in dem Programm.

10 Institut MD Universität Rostock Hello World, Versuch II Ein Workaround zur Lösung der Wettlaufbedingungen. Vor dem Erzeugen des zweiten Threads und vor dem Aufruf der exit-Funktion eine kleine Verzögerung einfügen.

11 Institut MD Universität Rostock void print_message_function( void *ptr ); main() { pthread_t thread1, thread2; char *message1 = "Hello"; char *message2 = "World"; pthread_create( &thread1, pthread_attr_default, (void*)&print_message_function, (void*) message1); sleep(10); pthread_create(&thread2, pthread_attr_default, (void*)&print_message_function, (void*) message2); sleep(10); exit(0); } void print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); } Hello World, Versuch II

12 Institut MD Universität Rostock Diskussion

13 Institut MD Universität Rostock Diskussion Es ist niemals sicher, sich auf Zeitverzögerungen zu verlassen, um eine Synchronisation durchzuführen Die Wettlaufbedingungen sind die gleichen wie bei parallelen Prozessen, die sich eine Ressource teilen. Ressource ist hier. Mit sleep() wurde ein regelrechter Schnitzer eingefügt: sleep() u. exit() sind Systemrufe, die prozess-spezifisch sind D.h. mit sleep() geht der ganze Prozess schlafen. So dass folglich die gleiche Situation vorherrscht, wie in dem Beispiel ohne sleep().

14 Institut MD Universität Rostock Synchronisation zwischen Erzeuger und den kreierten Threads pthread_tsome_thread; intexit_value; int*exit_status=&exit_value; // do something // create thread // work with thread // exit now pthread_join( some_thread, &exit_status ); Aufrufender Thread wird suspendiert, bis angegebener Thread terminiert Synchronisation möglich, sinnvoll vor allem für exit() Auswertung des Rückgabewertes möglich

15 Institut MD Universität Rostock Verzögerung eines Threads pthread_delay_np (np = not portable) struct timespec delay; delay.tv_sec = 2; delay.tv_nsec = 0; pthread_delay_np( &delay )

16 Institut MD Universität Rostock Synchronisation: Mutex Using A Mutex: Accessing Shared Data In einem multithreaded Programm müssen alle gemeinsam genutzten Daten, durch Anwendung von Mutexen geschützt werden. Nur derjenige Prozess, der im Besitz eines Mutexes ist (es belegt hat), hat Zugriff auf eine gemeinsam genutzte Ressource.

17 Institut MD Universität Rostock Mutex Daten Zustand THREAD1 lock Mutex update Data Unlock Mutex THREAD2 lock Mutex update Data Unlock Mutex

18 Institut MD Universität Rostock Mutex-Funktionen Mutexe sichern den Zugang zum kritischen Abschnitt Posix-Funktionen: –pthread_mutex_init(sem, init) –pthread_mutex_lock (sem) –pthread_mutex_trylock(sem) –pthread_mutex_unlock (sem) –pthread_mutex_destroy (sem) Achtung: Mutex-Funktionen immer paarweise in möglichst kurzen und übersichtlichen Abschnitten benutzen

19 Institut MD Universität Rostock Mutex Mutex ist eine einfache (speicherlose) Semaphore pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int pthread_mutex_init ( … ); int pthread_mutex_destroy ( … ); Mutex verwenden: int pthread_mutex_lock ( … ); int pthread_mutex_trylock ( … ); int pthread_mutex_unlock ( … );

20 Institut MD Universität Rostock void reader_function(void); void writer_function(void); char buffer; int buffer_has_item = 0; pthread_mutex_t mutex; struct timespec delay; main() { pthread_t reader; delay.tv_sec = 2; delay.tv_nsec = 0; pthread_mutex_init(&mutex, pthread_mutexattr_default); pthread_create( &reader, pthread_attr_default, (void*)&reader_function,NULL); writer_function(); } Beispiel: Puffer mit einem Element. Synchronisation mit Mutex

21 Institut MD Universität Rostock void reader_function(void) { while(1) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 1) { consume_item( buffer ); buffer_has_item = 0; } pthread_mutex_unlock( &mutex ); pthread_delay_np( &delay ); } void writer_function(void) { while(1) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 0 ) { buffer = make_new_item(); buffer_has_item = 1; } pthread_mutex_unlock( &mutex ); pthread_delay_np( &delay ); } Beispiel: Puffer mit einem Element. Synchronisation mit Mutex

22 Institut MD Universität Rostock Mutex Mutex hat nur zwei Zustände: lock und unlock Entspricht einem binären Semaphor. POSIX-Mutexe können mit Condition Variable sinnvoll kombiniert werden. Z.B. derart dass ein Thread, der einem Mutex blockiert, auch auf ein Signal von einem anderen Thread warten kann. Wenn das Signal eintrifft, kann der blockierte Thread aufgeweckt werden und kann versuchen, das relevante Mutex zu belegen Was passiert, wenn pthread_delay_np() nicht benutzt wird?

23 Institut MD Universität Rostock Aufgabe Entwickeln Sie ein Programm, das Asciizeichen von einliest. Der Asciicode dieser Zeichen soll in einem zuvor erzeugten Thread reader ausgegeben werden. Wie können die Threads synchronisiert werden? Welche Probleme treten auf?

24 Institut MD Universität Rostock Diskussion Puffer kann nur ein Element aufnehmen –Schnellerer Thread wird auf Geschwindigkeit des langsameren abgebremst –Verschwendung von Rechenzeit durch Pollen von buffer_has_item Abbruchfunktionen fehleranfällig/kritisch: void writer_function(void) { char a; while( a != 'q' ) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 0 ) { a = make_new_item(); buffer=a; if ( a != 'q' ) buffer_has_item = 1; } pthread_mutex_unlock( &mutex ); } void writer_function(void) { while( 1 ) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 0 ) { buffer = make_new_item(); if ( buffer =='q' ) break; buffer_has_item = 1; } pthread_mutex_unlock( &mutex ); } void writer_function(void) { while( 1 ) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 0 ) { buffer = make_new_item(); buffer_has_item = 1; } pthread_mutex_unlock( &mutex ); if ( buffer =='q' ) break; }

25 Institut MD Universität Rostock Abbruchprobleme void reader_function(void) { char a=0; while( a!= 'q' ) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 1) { a=buffer; if ( a != 'q' ) consume_item(a); buffer_has_item = 0; } pthread_mutex_unlock( &mutex ); } void reader_function(void) { while( 1 ) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 1) { consume_item(buffer); buffer_has_item = 0; } pthread_mutex_unlock( &mutex ); if ( buffer==q ) break; } void reader_function(void) { char a; while( 1 ) { pthread_mutex_lock( &mutex ); if ( buffer_has_item == 1) { a=buffer; if ( a != 'q' ) consume_item(a); buffer_has_item = 0; } pthread_mutex_unlock( &mutex ); }

26 Institut MD Universität Rostock Condition Variable Using A Condition Variable: Scheduling Shared Ressources Wird verwendet, wenn der Programmierer die Art, wie mehrere Threads auf gemeinsam genutzte Ressourcen zugreifen, beeinflussen will und der typische Einer-Pro-Zeit-Gegenseitige Ausschluß nicht ausreicht.

27 Institut MD Universität Rostock Condition Variable Wird verwendet, um auf das Eintreffen bestimmter Ereignisse zu warten. Es können Informationen übertragen werden, die Auskunft über den Zustand gemeinsam genutzter Daten geben. Ist (im allgemeinen) mit einer einzelnen Bedingung für einer Zustandskomponente verbunden Ist verbunden mit einem Mutex, der den Zugriff auf die Zustandskomponente steuert. while (! predicate_on_condition (s)) pthread_cond_wait (&s, &v); Mutex CV1CV2 Daten Zustand

28 Institut MD Universität Rostock Condition Variable THREAD1 while (P1) wait CV1 Do A1 Mutex CV1CV2 Daten Zustand THREAD2 while (P2) wait CV2 Do A2 THREAD3 while (P1) wait CV1 Do B1 THREAD5 update state broadcast CV1 signal CV2 THREAD4 while (P2) wait CV2 Do B2

29 Institut MD Universität Rostock Condition Variable Eine CV ist immer mit einem bestimmten Mutex verbunden. Und mit den Daten, die durch das Mutex geschützt sind. Monitorkonzept wird damit realisierbar Ein Monitor besteht aus einem Mutex, Daten und keiner, einer oder mehrerer Bedingungen Es gibt drei Operationen: –Wait –Signal –Broadcast

30 Institut MD Universität Rostock Condition Variablen - Operationen Wait ( pthread_cond_wait) : Signal ( pthread_cond_signal ) : Broadcast ( pthread_cond_broadcast ) : TimedWait ( pthread_cond_timedwait ) : s.S.5 DEC-Paper

31 Institut MD Universität Rostock REACTOR lock state.m while pred (state.data) { wait state.cv } if pred (stat.data) { do actions; } unlock state.m Beispiel mit Conditions ACTOR lock state.m update state.data unlock state.m signal state.cv Mutex CV1CV2 Daten Zustand

32 Institut MD Universität Rostock Beispiel mit Conditions Dbuff - Example

33 Institut MD Universität Rostock void reader_function(void); void writer_function(void); char buffer; // ohne Verzögerung (s. Mutexsample) Semaphore writers_turn; Semaphore readers_turn; main() { pthread_t reader; semaphore_init( &readers_turn ); semaphore_init( &writers_turn ); /* writer must go first */ semaphore_down( &readers_turn ); pthread_create( &reader, pthread_attr_default, (void*)&reader_function,NULL); writer_function(); } Beispiel mit zählendem Semaphor –Keine Verschwendung von Rechenzeit zählendes Semaphor

34 Institut MD Universität Rostock void reader_function(void) { while(1) { semaphore_down( &readers_turn ); consume_item( buffer ); semaphore_up( &writers_turn ); } void writer_function(void) { while(1) { semaphore_down( &writers_turn ); buffer = make_new_item(); semaphore_up( &readers_turn ); } Beispiel mit zählendem Semaphor Sieht übersichtlicher aus.

35 Institut MD Universität Rostock Aufgabe zu Semaphoren Entwickeln Sie ein Programmm, das zwei Threads Writer und Reader erzeugt. Die Kommunikation zwischen den Threads soll über zählende Semaphoren gelöst werden. Der Writer hat die Aufgabe, eine stetig steigende Integerzahl nach Buffer zu schreiben. Zu beachten ist, dass Buffer eine Variable im kritischen Abschnitt ist! Der Reader soll diese Variable lesen und den Ascii- Code sowie das entsprechende Zeichen ausgeben. Alle Threads sollen sich definiert beenden, wenn Buffer den Wert q=112 erreicht hat.

36 Institut MD Universität Rostock Semaphore child_counter; Semaphore worlds_turn; main() { pthread_t thread1, thread2; char *message1 = "Hello"; char *message2 = "World"; semaphore_init( &child_counter ); semaphore_init( &worlds_turn ); semaphore_down( &worlds_turn );// world goes second // child_counter now must be up-ed 2 times for a thread blocked on it to be released semaphore_decrement( &child_counter );// value now 0 semaphore_decrement( &child_counter );// value now -1 pthread_create( &thread1, pthread_attr_default, void *) &print_message_function, (void *) message1); semaphore_down( &worlds_turn ); pthread_create(&thread2, pthread_attr_default, (void *) &print_message_function, (void *) message2); semaphore_down( &child_counter ); // not really necessary to destroy since we are exiting anyway semaphore_destroy ( &child_counter ); semaphore_destroy ( &worlds_turn ); exit(0); } Hello World mit zählendem Semaphor

37 Institut MD Universität Rostock void print_message_function( void *ptr ) { char *message; message = (char *) ptr; printf("%s ", message); fflush(stdout); semaphore_up( &worlds_turn ); semaphore_up( &child_counter ); pthread_exit(0); } Hello World mit zählendem Semaphor

38 Institut MD Universität Rostock Deadlock und Liveness Livelock: Prozesse, die für immer busy sind, auf ein spin lock wartend. Deadlock: Prozesse, die für immer suspendiert (schlafend) an einer Condition variable oder einer Lock-Operation sind. Starvation: Prozesse, die für unbestimmte Zeit aufgeschoben sind. Liveness: Prozesse, die frei von Deadlock, Livelock und Starvation sind

39 Institut MD Universität Rostock Sema, Mutex, CV Mit allen kann man sehr leicht Deadlocks produziert werden Es gibt einige Regeln, um Deadlock-Situationen zu reduzieren und einen sensiblen Gebrauch von Semaphor, Mutex und CV zu sichern. Eine Möglichkeit, um Deadlocks zu verhindern ist z.B. die Verwendung des Priority Ceiling Protocols

40 Institut MD Universität Rostock Wie viele und wie groß Mutexe können einzelne Daten oder Programmbereiche schützen –Wie dick sollte ein Mutex (d.h. der geschützte Bereich) sein? –Wie viele Zustandsvariablen sollten kombiniert werden und durch ein Mutex geschützt werden. Mutexes bewirken, dass Threads warten. Das hat Kontext switch zur Folge, der Zeit kostet. –Wenige und große Mutexe sind gut.

41 Institut MD Universität Rostock Speisende Philosphen mit Mutexe

42 Institut MD Universität Rostock Aufgabe Auf der Basis von Posix-Mutexe und Posix- Conditions zählende Semaphore implementieren.

43 Institut MD Universität Rostock pthread_t some_thread; if ( pthread_create( &some_thread,... ) == -1 ) { perror("Thread creation error"); exit(1); } Fehlerbehandlung nie vergessen!

44 Institut MD Universität Rostock Thread beenden Funktion Beschreibung pthread_cancel (thread_id) pthread_setcancelstate(stat, old) pthread_setcanceltype(typ, old) THREAD_CANCEL_ENABLE, THREAD_CANCEL_DISABLE pthread_testcancel() pthread_join pthread_cond_wait pthread_cond_timed_wait phread_testcancel sigwait Sem_wait

45 Institut MD Universität Rostock Thread terminieren Pthread_cleanup_push(func, arg) Pthread_cleanup_pop(exec) sigwait Sem_wait


Herunterladen ppt "Institut für Angewandte Mikroelektronik und Datentechnik Fachbereich Elektrotechnik und Informationstechnik, Universität Rostock Vorlesung Echtzeitbetriebssysteme."

Ähnliche Präsentationen


Google-Anzeigen