Semafory — przypomnienie Semafory w Uniksie
Transkrypt
Semafory — przypomnienie Semafory w Uniksie
Semafory — przypomnienie • semafory służą ochronie dostępu procesów do sekcji krytycznej; • na semaforach dostępne są dwie operacje: – podniesienie semafora signal, – opuszczenie semafora wait — opuszczony semafor nie daje się już dalej opuścić i proces, który sobie tego życzy, musi poczekać, aż inny proces podniesie semafor; • proces, korzystający z sekcji krytycznej chronionej przez semafor S: ··· operacje prywatne procesu; ··· wait(S); operacje w sekcji krytycznej; signal(S); ··· operacje prywatne procesu; ··· Wykład 8, 29 IV 2008, str. 2 Semafory w Uniksie Potrzebny plik nagłówkowy — #include "semafory.h" : #include #include #include #include #include #include <stdio.h> <stdlib.h> <sys/ipc.h> <sys/sem.h> <sys/shm.h> <sys/types.h> typedef int Semafor; typedef void* Wsp_pamiec; void blad (char* s); Semafor ustaw_semafor (key_t nazwa, int start); Semafor usun_semafor (Semafor sem); void signal (Semafor sem); void wait (Semafor sem); Wsp_pamiec utworz_pamiec (key_t nazwa, int rozm); Semafory w Uniksie Użycie pliku nagłówkowego w programie: gcc semafory.c moj_program.c W programie moj_program.c musi być dyrektywa #include "semafory.h" Wykład 8, 29 IV 2008, str. 4 Semafory w Uniksie Deklaracja i inicjalizacja semafora: typedef int Semafor; Semafor ustaw_semafor (key_t nazwa, int start); — wprowadza nowy semafor: • nazwa — nazwa semafora, • start — początkowa wartość (dla semafora binarnego: 1), • wartość wynikowa — identyfikator semafora do używania w programie. Przykład: M Semafor sem = ustaw_semafor ((key_t)123, 1); Semafory w Uniksie Usuwanie semafora: void usun_semafor (Semafor sem); — usuwa semafor: • sem — identyfikator semafora (wprowadzony przez ustaw_semafor()). Operacje na semaforze: void void signal (Semafor sem); wait (Semafor sem); — podniesienie i opuszczenie semafora: • signal(sem) — podniesienie semafora sem, • wait(sem) — opuszczenie semafora sem. Wykład 8, 29 IV 2008, str. 6 Przykład użycia semafora — producent Semafor sem = ustaw_semafor ((key_t)123, 1); ... p = produkuj(); juz=0; do { wait(sem); if (bufor nie jest pełny) { włóż p do bufora; juz=1; } signal(sem); } while (! juz); ... Przykład użycia semafora — konsument Semafor sem = ustaw_semafor ((key_t)123, 1); ... juz=0; do { wait(sem); if (bufor nie jest pusty) { wyjmij z bufora do p; juz=1; } signal(sem); } while (! juz); konsumuj(p); ... Wykład 8, 29 IV 2008, str. 8 Lokalność zmiennych w procesie Musimy jeszcze zrealizować komendy wyżej nieformalnie opisane jako: • bufor nie jest pusty, • bufor nie jest pełny, • włóż p do bufora, • wyjmij z bufora do p. Każdy proces ma własną przestrzeń nazw, więc bufor zadeklarowany w jednym procesie będzie niedostępny w innym. Np. fragment programu int n=3; if (fork()) { n++; printf("%i\n", n); } else { n--; printf("%i\n", n); } wydrukuje 4 i 2 — wartości dwóch różnych zmiennych n. Jak zmusić konsumenta i producenta do pracy na tym samym buforze? Wspólna pamięć w Uniksie Deklaracja i inicjalizacja wspólnej pamięci: typedef void* Wsp_pamiec; Wsp_pamiec utworz_pamiec (key_t nazwa, int rozm); — wprowadza nową wspólną pamięć: • nazwa — nazwa wspólnej pamięci, • rozm — liczba bajtów wspólnej pamięci, • wartość wynikowa — wskaźnik na utworzoną wspólną pamięć. Przykład: Mstruct dane_st { int bufor[ROZM_BUFORA]; int in; int out; }; struct dane_st * dane; Wsp_pamiec pam = utworz_pamiec((key_t)123, sizeof(*dane)); dane = (struct dane_st *)pam; Wykład 8, 29 IV 2008, str. 10 Wspólna pamięć w Uniksie Operacje na wspólnej pamięci: — poprzez pola struktury dane: • dane->bufor • dane->in • dane->out