Mariusz Rudnicki PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO CZ.4

Podobne dokumenty
Mariusz Rudnicki PROGRAMOWANIE WSPÓŁBIEŻNE I SYSTEMY CZASU RZECZYWISTEGO CZ.4

w odróżnieniu od procesów współdzielą przestrzeń adresową mogą komunikować się za pomocą zmiennych globalnych

Programowanie równoległe i rozproszone. Monitory i zmienne warunku. Krzysztof Banaś Programowanie równoległe i rozproszone 1

1. Uruchom poniższy program tworzący pojedynczy wątek:

Programowanie równoległe i rozproszone. W1. Wielowątkowość. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Temat zajęć: Tworzenie i obsługa wątków.

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO. Mariusz RUDNICKI: pok. 753 tel.:

Wielowątkowy serwer TCP

Problemy współbieżności

Programowanie współbieżne Wykład 10 Synchronizacja dostępu do współdzielonych zasobów. Iwona Kochańska

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

synchronizacji procesów

synchronizacji procesów

Systemy operacyjne III

Synchronizacja procesów i wątków

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Implementacje zgodne z tym standardem są nazywane wątkami POSIX lub Pthreads.

Wykład 5. Synchronizacja (część II) Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Wielozadaniowość w systemie Microsoft Windows

Stworzenie klasy nie jest równoznaczne z wykorzystaniem wielowątkowości. Uzyskuje się ją dopiero poprzez inicjalizację wątku.

Od uczestników szkolenia wymagana jest umiejętność programowania w języku C oraz podstawowa znajomość obsługi systemu Linux.

Futex (Fast Userspace Mutex) Łukasz Białek

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację.

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Tworzenie wątków. #include <pthread.h> pthread_t thread;

1. Procesy i współbieżność

Programowanie współbieżne Wykład 9 Synchronizacja dostępu do współdzielonych zasobów. Iwona Kochańska

SYSTEMY CZASU RZECZYWISTEGO - VxWorks

Wykład 4. Synchronizacja procesów (i wątków) cześć I. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Dzisiejszy wykład. Klasa string. wersja prosta wersja ze zliczaniem odwołań. Wyjątki Specyfikator volatile Semafory

Modele programowania równoległego. Pamięć współdzielona Rafał Walkowiak dla III roku Informatyki PP

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Przeplot. Synchronizacja procesów. Cel i metody synchronizacji procesów. Wątki współbieżne

Mariusz Rudnicki PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO CZ.2

ZAJECIA Z SYSTEMÓW OPERACYJNYCH 2 (Programowanie): funkcje POSIX

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Wykład 4. Synchronizacja procesów (i wątków) cześć I. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Przetwarzanie wielowątkowe przetwarzanie współbieżne. Krzysztof Banaś Obliczenia równoległe 1

Systemy Operacyjne 2: Wątki pthreads. dr inż. Arkadiusz Chrobot

Współbieżność w środowisku Java

Gdy kilka procesów czyta a przynajmniej jeden dokonuje zapisu wynik odczytu zależeć może od sposobu realizacji przeplotu.

Mechanizmy pracy równoległej. Jarosław Kuchta

Wskaźniki w C. Anna Gogolińska

Programowanie w języku C++

Klasy Obiekty Dziedziczenie i zaawansowane cechy Objective-C

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Semafor nie jest mechanizmem strukturalnym. Aplikacje pisane z użyciem semaforów są podatne na błędy. Np. brak operacji sem_post blokuje aplikację.

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Programowanie współbieżne Wykład 7. Iwona Kochaoska

Plan wykładu. Obliczenia równoległe w zagadnieniach inżynierskich. Wykład 1 p. Wzajemne wykluczanie. Procesy współbieżne

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Tablice, funkcje - wprowadzenie

Synchronizacja procesów

Podstawy programowania. Wykład: 7. Funkcje Przekazywanie argumentów do funkcji. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Wykład 7 Podręczna pamięć buforowa (ang. buffer cache) w systemie Linuks. Wojciech Kwedlo, Systemy Operacyjne II -1- Wydział Informatyki PB

Systemy operacyjne. Zajęcia 11. Monitory

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

procesów Współbieżność i synchronizacja procesów Wykład prowadzą: Jerzy Brzeziński Dariusz Wawrzyniak

Plan wykładu. Programowanie aplikacji równoległych i rozproszonych. Wykład 1 p. Wzajemne wykluczanie. Procesy współbieżne

Programowanie aplikacji równoległych i rozproszonych. Wykład 1

procesy odrębne dzielone

Tworzenie programów równoległych cd. Krzysztof Banaś Obliczenia równoległe 1

Wykład 5: Klasy cz. 3

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Programowanie Współbieżne

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Lab 9 Podstawy Programowania

Wykład 1: Wskaźniki i zmienne dynamiczne

Podstawy programowania współbieżnego. 1. Wprowadzenie. 2. Podstawowe pojęcia

Języki i metodyka programowania. Wskaźniki i tablice.

Od uczestników szkolenia wymagana jest umiejętność programowania w języku C oraz podstawowa znajomość obsługi systemu Windows.

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

Problemy czytelników i pisarzy oraz 5 ucztujących filozofów

Podstawy programowania komputerów

Argumenty wywołania programu, operacje na plikach

Projektowanie oprogramowania systemów WĄTKI I SYNCHRONIZACJA

7. Pętle for. Przykłady

Proces z sekcją krytyczną. Synchronizacja procesów. Synchronizacja procesów, cd. Synchronizacja procesów, cd. Synchronizacja procesów, cd

Systemowe mechanizmy synchronizacji procesów

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Wielowątkowość mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Procesy i wątki. Krzysztof Banaś Obliczenia równoległe 1

Problemy czytelników i pisarzy oraz 5 ucztujących filozofów

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Wskaźniki. Programowanie Proceduralne 1

Kolejki FIFO (łącza nazwane)

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Programowanie Równoległe i Rozproszone

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Obliczenia równoległe i rozproszone w JAVIE. Michał Kozłowski 30 listopada 2003

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Język C zajęcia nr 11. Funkcje

Zaawansowane programowanie w języku C++ Zarządzanie pamięcią w C++

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Tworzenie i zarządzanie wątkami

POSIX: IEEE Std (Issue 6, 2004 edition)

Mechanizmy z grupy IPC

Transkrypt:

Mariusz Rudnicki mariusz.rudnicki@eti.pg.gda.pl PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO CZ.4

Synchronizacja wątków Omawiane zagadnienia Czym jest synchronizacja wątków? W jakim celu stosuje się mechanizmy synchronizacji? Metody synchronizacji w RT OS: QNX Neutrino, RT Linux, Windows CE. Niebezpieczeństwa związane z synchronizacją. 2/49

Synchronizacja wątków Wątki dostarczają nowych rozwiązań ale także nowych problemów: Wspólne obszary pamięci: wielokrotne zapisy mogą zamazać oczekiwaną wartość, wątek czytający dane nie wie, kiedy dane są stabilne lub jeszcze nie, Podobne problemy występują z innymi współdzielonymi zasobami... 3/49

Synchronizacja wątków Problem stanowi synchronizacja pracy wątków. Rozwiązaniem problemu synchronizacji są metody przedstawione w dalszej części prezentacji. Szerzej omawiane: mutexy, zmienne warunkowe, semafory, operacje atomowe. 4/49

Synchronizacja wątków Pozostałe metody stosowane w QNX Neutrino: rwlocks: pozwala na wielokrotne czytanie bez możliwości zapisu, tylko jeden zapis bez możliwości czytania, jednokrotna inicjalizacja: Pierwsze wywołanie pthread_once z danym argumentem once_control powoduje wykonanie kodu bezargumentowej procedury init_routine i zmienia wartość zmiennej once_control żeby zaznaczyć, ze inicjalizacja była wykonana. Kolejne wywołania pthread_once z tym samym argumentem once_control będą pustymi wywołaniami; 5/49

Synchronizacja wątków Pozostałe metody stosowane w QNX Neutrino: dane własne wątku: Zmienne są powielane dla każdego wątku i każdy może modyfikować swoją kopię zmiennej bez wpływu na inne wątki. 6/49

Synchronizacja wątków słowo kluczowe volatile: zmienne współdzielone: powinny być zadeklarowane jako volatile; volatile unsigned flags;... atomic_clr (&flags, A_FLAG); volatile jest słowem kluczowym ANSI C informującym kompilator żeby nie optymalizował tej zmiennej. przykład: Kompilator może optymalizować kod umieszczając wartości w rejestrze i odnosząc się do rejestru zamiast sięgania do pamięci. Tymczasem inny wątek uzyskiwałby dostęp do pamięci! 7/49

Synchronizacja Mutual Exclusion Mutual exclusion zgodny z POSIX. Wzajemne wykluczenie ang. Mutual exclusion oznacza, że tylko jeden wątek: ma dostęp do krytycznej sekcji kodu w danym momencie; ma dostęp do szczególnego fragmentu danych w danej chwili. 8/49

Synchronizacja Mutual Exclusion Wzajemne wykluczanie projektuje się tak, by zsynchronizować wątki w taki sposób, aby każdy przetwarzał dane i wykonywał sekcję krytyczną w sposób nie kolidujący z wykonaniem sekcji krytycznej innych wątków. Do realizacji tego zagadnienia, należy do funkcji każdego wątku dodać dodatkowe instrukcje poprzedzające i następujące po sekcji krytycznej. 9/49

Synchronizacja Mutual Exclusion API dostarcza następujących wywołań: administracyjnych: pthread_mutex_init (pthread_mutex_t *, pthread_mutexattr_t *); pthread_mutex_destroy (pthread_mutex_t *); użytkowych: pthread_mutex_lock (pthread_mutex_t *); pthread_mutex_trylock (pthread_mutex_t *); pthread_mutex_unlock (pthread_mutex_t *); 10/49

Synchronizacja Mutual Exclusion Przykład: pthread_mutex_t mymutex; init () { domyślne... atrybuty // utworzenie mutexu pthread_mutex_init (&mymutex, NULL);... thread_func () {... // otrzymaj mutex, czekaj w razie potrzeby pthread_mutex_lock (&mymutex); // operowanie na krytycznych danych // koniec krytycznej sekcji, zwolnij mutex pthread_mutex_unlock (&mymutex);... cleanup () { pthread_mutex_destroy (&mymutex); 11/49

Synchronizacja Mutual Exclusion Rozważmy sytuację: freelist Pewna liczba wątków żąda alokacji pamięci wywołując funkcję malloc(). Wewnętrznie, malloc() przechowuje listę wolnych bloków pamięci, które są dostępne do alokacji. Wszystkie wątki w procesie używają tej samej listy. memoryarea 1 memoryarea 2 memoryarea 3 memoryarea 4 NULL 12/49

Synchronizacja Mutual Exclusion W uproszczeniu źródło malloc() wygląda następująco: void * malloc (int nbytes) { while (freelist && freelist -> size!= nbytes) { freelist = freelist -> next; if (freelist) { // mark block as used, and return block address to caller return (freelist -> memory_block); 13/49

Synchronizacja Mutual Exclusion Rozważmy pewną liczbę wątków, które używają malloc(): thread1 () { char *data; data = malloc (64); thread2 () { char *other_data; other_data = malloc (64); 14/49

Synchronizacja Mutual Exclusion 15/49

Synchronizacja Mutual Exclusion Problem stanowi rywalizacja wątków o wspólne zasoby, wiele wątków może wchodzić sobie w drogę! Rozwiązaniem problemu jest wyłączny dostęp do struktury danych! Rozwiązanie z użyciem mutexu! 16/49

Synchronizacja Mutual Exclusion Poprawiony kod funkcji malloc(): pthread_mutex_t malloc_mutex; void * malloc (int nbytes) { pthread_mutex_lock (&malloc_mutex); while (freelist && freelist -> size!= nbytes) { freelist = freelist -> next; if (freelist) { // mark block as used, and return block block = freelist -> memory_block; pthread_mutex_unlock (&malloc_mutex); return (block); pthread_mutex_unlock (&malloc_mutex); 17/49

Synchronizacja Mutual Exclusion Aby zainicjować mutex należy wykonać następujący fragment kodu: pthread_mutex_init (&malloc_mutex, NULL); Jeżeli zakończy się powodzeniem gwarantuje, że wszystkie odpowiednie zasoby zostały zaalokowane dla mutexa. 18/49

Synchronizacja Mutual Exclusion Prosta metoda inicjalizacji mutexu: // statyczna inicjalizacja Mutexu pthread_mutex_t malloc_mutex = PTHREAD_MUTEX_INITIALIZER; void * malloc (int nbytes) {... // MUTEX będzie zainicjowany po pierwszym //użyciu pthread_mutex_lock (&malloc_mutex);... 19/49

Synchronizacja Mutual Exclusion Domyślnie mutexy nie mogą być współdzielone między procesami; aby współdzielić mutexa, ustawiamy dla niego flagę PTHREAD_PROCESS_SHARED; mutex powinien być zdefiniowany w pamięci współdzielonej; np.: pthread_mutexattr_t mutex_attr; pthread_mutex_t *mutex; pthread_mutexattr_init( &mutex_attr ); pthread_mutexattr_setpshared( &mutex_attr, PTHREAD_PROCESS_SHARED); mutex = (pthread_mutex_t *)shmem_ptr; pthread_mutex_init( mutex, &mutex_attr ); 20/49

Synchronizacja Mutual Exclusion Pamiętaj! Żaden wątek nie może wykonywać swej sekcji krytycznej nieskończenie długo, nie może się w niej zapętlić lub zakończyć w wyniku jakiegoś błędu; W sekcji krytycznej wątek przebywa jak najkrócej i nie może zakończyć się błędem. 21/49

Synchronizacja Condition variables Rozważmy prosty przypadek, gdzie: musimy zablokować wątek, oczekując aż inny wątek zmieni pewną zmienną: int state; thread_1 (){ while (1) { // wait until state changes, // then, perform some work zmienne warunkowe dostarczają mechanizm oczekiwania na taką zmianę 22/49

Synchronizacja Condition variables Wywołania: pthread_cond_init (pthread_cond_t *, pthread_condattr_t *); pthread_cond_wait (pthread_cond_t *, pthread_mutex_t *); pthread_cond_signal (pthread_cond_t *); pthread_cond_broadcast (pthread_cond_t *); 23/49

Synchronizacja Condition variables Wywołania: wątek dostarczający dane dostaje pewną ich ilość, np. od procesu klienta, i dodaje je do kolejki powiadamia wątek obsługi sprzętu o nowych danych wątek obsługi sprzętu budzi się, pobiera dane z kolejki i przesyła je do sprzętu. 24/49

Synchronizacja Condition variables Żeby to wykonać potrzebujemy dwóch rzeczy: mutexa aby zapewnić pojedynczy dostęp do kolejki danych, mechanizm dla wątku dostarczającego dane by poinformował wątek obsługi sprzętu o nowych danych i obudził go. 25/49

Synchronizacja Condition variables Kod wątku obsługi sprzętu: while (1) { pthread_mutex_lock (&mutex); // wyłączność dostępu if (!data_ready) pthread_cond_wait (&cond, &mutex); // oczekiwanie na dane /* pobranie danych z kolejki */ while ((data = get_data_and_remove_from_queue ())!= NULL) { pthread_mutex_unlock (&mutex); write_to_hardware (data); // przekaż do urządzenia free (data); // zwolnij zasoby pthread_mutex_lock (&mutex); data_ready = 0; // ponowne ustawienie flagi pthread_mutex_unlock (&mutex); 26/49

Synchronizacja Condition variables Kod wątku dostarczającego dane: pthread_mutex_lock (&mutex); // wyłączność dostępu add_to_queue (buf); data_ready = 1; // ustawienie flagi pthread_cond_signal (&cond); // powiadomienie oczekującego pthread_mutex_unlock (&mutex); // zwolnienie dostępu 27/49

Synchronizacja Condition variables Przyjrzyjmy się bliżej funkcji wait : pthread_cond_wait (&condvar, &mutex); Zwalnia rygiel z mutexu podanego jako drugi parametr (dlatego przed wywołaniem tej funkcji wątek powinien zaryglować tego mutexa), następnie usypia aktualny wątek. Podczas sukcesu ponownie ustawia rygiel na podanym mutexie i zwraca 0. 28/49

Synchronizacja Condition variables Dlaczego wykonujemy to sprawdzenie? while (1) { 2 1 pthread_mutex_lock (&mutex); if (data_ready == 0)... // wyłączny dostęp pthread_cond_wait (&cond, &mutex); // oczekujemy data_ready = 0; pthread_mutex_unlock (&mutex); // ponownie ustawiamy flagę jeżeli sygnalizujemy zmienną warunkową i żaden wątek nie czeka na sygnał, jest on tracony; sygnał powinien być wysłany pomiędzy 1 i 2 ; proces sygnalizujący ustawia też flagę (data_ready = 1) 29/49

Synchronizacja Condition variables Sygnalizacja vs broadcast: wątki 1, 2 i 3 (wszystkie o takim samym priorytecie) czekają na zmianę używając pthread_cond_wait(), Wątek 4 dokonuje zmianę i sygnalizuje za pomocą pthread_cond_signal(), Najdłużej czekający wątek (powiedzmy 2 ) jest informowany o zmianie i próbuje zablokować mutex ( automatycznie przez pthread_cond_wait()), Wątek 2 sprawdza warunek, przeprowadza działania lub wraca do uśpienia 30/49

Synchronizacja Condition variables Co się dzieje z wątkami 1 i 3? nigdy nie zauważą zmiany! Jeżeli zmienimy przykład: wykorzystamy pthread_cond_broadcast() zamiast pthread_cond_signal(), wtedy wszystkie trzy wątki otrzymają powiadomienie wszystkie wątki zmienią stan na READY, jednak tylko jeden z nich może zablokować mutex jednocześnie - pozostałe kolejno. 31/49

Synchronizacja Condition variables Co wybrać? wybieramy sygnał, jeżeli: mamy jeden oczekujący wątek; potrzebujemy uruchomić tylko jeden wątek do przetwarzania i nie musimy informować pozostałych; używamy broadcast, jeżeli mamy wiele wątków i: wszystkie muszą przeprowadzić działania po dokonanej zmianie; lub nie wszystkie potrzebują dostępu do zmiany, ale nie wiemy, który z nich obudzić. 32/49

Synchronizacja Condition variables Domyślnie, zmienne warunkowe nie mogą być współdzielone z innymi procesami: aby współdzielić zmienne warunkowe, ustawiamy odpowiednią flagę PTHREAD_PROCESS_SHARED: zmienna warunkowa powinna być w pamięci współdzielonej: pthread_condattr_t cond_attr; pthread_cond_t *cond; pthread_condattr_init( &cond_attr ); pthread_condattr_setpshared( &cond_attr, PTHREAD_PROCESS_SHARED); cond = (pthread_cond_t *)shmem_ptr; pthread_cond_init(cond, &cond_attr ); 33/49

Synchronizacja Condition variables Przykład producenta/konsumenta: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; volatile int state = 0; volatile int product = 0; void *consume (void *arg) { while (1) { pthread_mutex_lock (&mutex); while (state == 0) { pthread_cond_wait (&cond, &mutex); printf ( Consumed %d\n, product); state = 0; pthread_cond_signal (&cond); pthread_mutex_unlock (&mutex); do_consumer_work (); return (0); 34/49

Synchronizacja Condition variables Przykład producenta/konsumenta: pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; volatile int state = 0; volatile int product = 0; void *consume (void *arg) { while (1) { pthread_mutex_lock (&mutex); while (state == 0) { pthread_cond_wait (&cond, &mutex); printf ( Consumed %d\n, product); state = 0; pthread_cond_signal (&cond); pthread_mutex_unlock (&mutex); do_consumer_work (); return (0); 35/49

Synchronizacja Condition variables void *produce (void *arg) { while (1) { pthread_mutex_lock (&mutex); while (state == 1) { pthread_cond_wait (&cond, &mutex); printf ( Produced %d\n, product++); state = 1; pthread_cond_signal (&cond); pthread_mutex_unlock (&mutex); do_producer_work (); return (0); int main () { pthread_create (NULL, NULL, &produce, NULL); consume (NULL); return (EXIT_SUCCESS); 36/49

Synchronizacja Semaphores Semafor - jest obiektem abstrakcyjnym służącym do kontrolowania dostępu do ograniczonego zasobu. Semafory są szczególnie przydatne w środowisku gdzie wiele procesów lub wątków komunikuje się przez wspólną pamięć. 37/49

Synchronizacja Semaphores W standardzie POSIX wyróżnione są dwa typy semaforów: Semafory nienazwane identyfikowane po adresie semafora. Stąd nazwa semafor nienazwany. Semafory nazwane - identyfikowane są w procesach poprzez ich nazwę. Na semaforze nazwanym operuje się tak samo jak na semaforze nienazwanym z wyjątkiem funkcji otwarcia i zamknięcia semafora. 38/49

Synchronizacja Semaphores Wykorzystanie semaforów dla sterowania dostępem administracja: sem_init (sem_t *semaphore, int pshared, unsigned int val); sem_destroy (sem_t *semaphore); unnamed semaphores sem_t *sem_open (char *name, int oflag, [int sharing, unsigned int val]); sem_close (sem_t *semaphore); named semaphores sem_unlink (char *name); użycie: sem_post (sem_t *semaphore); sem_trywait (sem_t *semaphore); sem_wait (sem_t *semaphore); sem_getvalue (sem_t *semaphore, int *value); 39/49

Synchronizacja Semaphores Nienazwane vs nazwane semafory: z nienazwanymi, wywołania sem_post() i sem_wait() powodują bezpośrednie wywołanie jądra związane z semaforem, z nazwanymi, wywołania sem_post() i sem_wait() wysyłają komunikaty do mqueue a stąd generowane są wywołania jądra, semafory nienazwane są szybsze niż nazwane, semafory nazwane wykorzystywane są do komunikacji pomiędzy procesami. 40/49

Synchronizacja RT Linux: mutexy, semafory zgodne z POSIX. 41/49

Synchronizacja Windows Embedded obiekty synchronizacji wątków: sekcje krytyczne, mutexy, zdarzenia, semafory, funkcje oczekujące. 42/49

Synchronizacja Windows Embedded sekcje krytyczne: chronią część kodu przed dostępem wielu wątków w jednym czasie, mogą być wykorzystywane w obrębie jednego procesu lub DLL, nie mogą być współdzielone przez inne procesy. void InitializeCriticalSection (LPCRITICAL_SECTION lpcriticalsection); void EnterCriticalSection (LPCRITICAL_SECTION lpcriticalsection); void LeaveCriticalSection (LPCRITICAL_SECTION lpcriticalsection); void DeleteCriticalSection (LPCRITICAL_SECTION lpcriticalsection); 43/49

Synchronizacja Windows Embedded mutexy: są obiektami, których stan sygnalizuje czy są używane przez wątek; koordynują wyłączny dostęp do współdzielonych zasobów; w danym czasie tylko jeden wątek może używać mutexa; mutex może być uważany za porzucony ang. abandoned w sytuacji gdy wątek zakończy pracę i nie zwolni mutexa; wątek oczekujący może uzyskać prawa do mutexa porzuconego; 44/49

Synchronizacja Windows Embedded mutexy: pojawienie się mutexa porzuconego sygnalizuje, że wystąpił błąd w systemie i stan wszelkich zasobów chronionych tym mutexem jest nieokreślony; jeżeli wątek uzna, że mutex nie jest porzucony i kontynuuje pracę to po zwolnieniu mutexa flaga porzucony zostaje skasowana i staje się on zwykłym mutexem; mutexy mogą być używane w synchronizacji pracy wielu procesów. 45/49

Synchronizacja Windows Embedded semafory: są obiektami: synchronizacji wątków wewnątrz jednego procesu, jak również synchronizacji międzyprocesowej; stan semafora jest sygnalizowany, kiedy jego licznik jest większy od zera i nie jest sygnalizowany, gdy licznik równy jest zero; semafor jest bramą użycia zasobu ograniczającą jego użycie poprzez zliczanie wątków przechodzących przez bramę; 46/49

Synchronizacja Windows Embedded semafory: za każdym razem gdy wątek oczekujący jest przepuszczany licznik semafora jest zmniejszana; aplikacja może stworzyć semafor z licznikiem = 0 wówczas, powoduje to jego ustawienie w stan niesygnalizowany i blokuje wszystkie wątki żądające dostępu do chronionego zasobu. 47/49

Synchronizacja Windows Embedded zdarzenia: zdarzenia są obiektami wykorzystywanymi do: powiadamiania wątku kiedy ma wykonać swoją pracę; wskazania, że dane zdarzenia miało miejsce; nazwane zdarzenia mogą być wykorzystywane do synchronizacji wątków różnych procesów. 48/49

Synchronizacja Windows Embedded funkcje oczekujące: są obiektami blokującymi lub odblokowującymi wątek, bazującymi na stanie obiektu: oczekiwanie na jeden obiekt WaitForSingleObject; oczekiwanie na wiele obiektów WaitForMultipleObjects; oczekiwanymi obiektami mogą być obiekty synchronizacji np. mutexy lub zdarzenia bądź też uchwyty do procesów lub wątków; funkcje oczekujące na wiele obiektów tworzą tablicę zawierającą jeden lub więcej obiektów synchronizacji np.: stan obiektu synchronizaji; upłynięcie określonego czasu. 49/49