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