Microsoft Word Dokument1(1) id 299101

background image

10. Synchronizacja użycia zasobów, Semafory

10.1 Podstawy synchronizacji, kanoniczne operacje synchronizacyjne
Rodzaje współpracy procesów współbieżnych:

Współbieżność kooperacyjna
Procesy współpracują ze sobą w ramach jednej aplikacji która ma realizować pewne
zadanie. Synchronizacja polega na zapewnieniu koordynacji procesów

Współbieżność konkurencyjna
We wspólnym środowisku działa wiele procesów lub wątków dzieląc zasoby tego
środowiska. System operacyjny musi zapewnić koordynację w dostępie do
wspólnych zasobów.

W obydwu przypadkach wyodrębnić można dwie kanoniczne operacje
synchronizacyjne Suspend i Resume:

Suspend(Queue K) – zawieszenie procesu bieżącego w kolejce K

Kroki procedury Suspend
Stan procesu bieżącego zapamiętywany jest w jego deskryptorze.

1. Deskryptor usuwany jest z kolejki procesów gotowych i umieszczany w kolejce

K.

2. Uruchamiana jest procedura szeregująca która wybiera do wykonania pewien

proces z kolejki procesów gotowych.

Ready

Next

PD

Next

PD

NIL

PD

Kolejka procesów gotowych

Proces bieżący

K

Next

PD

Next

PD

NIL

PD

Kolejka procesów zawieszonych

Kolejka

Suspend(K)

Wskaźnik na

kolejkę

procesów
gotowych

PD - pola

deskryptora

procesu

background image


Resume(Queue K) - Wznowienie pierwszego procesu z kolejki K

Kroki procedury Resume

1. Deskryptor pierwszego procesu z kolejki K jest przenoszony z tej kolejki do

kolejki procesów gotowych.

2. Uruchamiana jest procedura szeregująca która wybiera do wykonania pewien

proces z kolejki procesów gotowych.



Ready

Next

PD

Next

PD

NIL

PD

Kolejka procesów gotowych

Proces bieżący

K

Next

PD

Next

PD

NIL

PD

Kolejka procesów zawieszonych

Kolejka

Wskaźnik na

kolejkę

procesów
gotowych

Resume(K)



Nieraz niezbędna jest procedura Resume(K,P) – wznowienie procesu P (P – PID
procesu) z kolejki K.

background image

10.2 Problem producenta i konsumenta

Zagadnienie kontroli użycia jednostek zasobu
W systemie istnieje pula N jednostek zasobu pewnego typu. Procesy mogą pobierać
z puli zasoby i je zwracać. Gdy brak jest zasobu a pewien proces będzie próbował go
pobrać ulega on zablokowaniu. Proces zostanie odblokowany gdy inny proces zwróci
jednostkę zasobu.

1. W systemie istnieją dwie grupy procesów – producenci i konsumenci oraz bufor

na elementy.

2. Producenci produkują pewne elementy i umieszczają je w buforze.
3. Konsumenci pobierają elementy z bufora i je konsumują .
4. Producenci i konsumenci przejawiają swą aktywność w nie dających się określić

momentach czasu.

5. Bufor ma pojemność na N elementów.

BUFOR N - elementów

Zajęte

Wolne

P1

P2

Pk

Producenci

K1

K2

Kl

Konsumenci

Należy prawidłowo zorganizować pracę systemu.
1. Gdy są wolne miejsca w buforze producent może tam umieścić swój element.

Gdy w buforze brak miejsca na elementy producent musi czekać. Gdy wolne
miejsca się pojawią producent zostanie odblokowany.

2. Gdy w buforze są jakieś elementy konsument je pobiera. Gdy brak elementów w

buforze konsument musi czekać. Gdy jakiś element się pojawi, konsument
zostanie odblokowany.


Bufor zorganizowany może być na różnych zasadach.
1. Kolejka FIFO (bufor cykliczny).
2. Kolejka LIFO (stos).

Umieszczanie / pobieranie elementu z bufora jest sekcją krytyczną.


background image

10.3 Problem czytelników i pisarzy
W systemie istnieją dwie grupy procesów – czytelnicy i pisarze. Czytanie może się
odbywać współbieżnie z innymi procesami natomiast pisanie, w celu zapewnienia
spójności danych, musi się odbywać na zasadzie wyłączności.

Wielu czytelników

C1

C2

CN

P

Jeden pisarz

Baza danych

- Czytelnik

może wejść do czytelni gdy jest ona pusta lub gdy są tam inni

czytelnicy

- Pisarz

może wejść do czytelni gdy jest ona pusta



Problem jest uogólnieniem problemu dostępu wielu procesów do bazy danych.

10.4 Problem

śpiącego fryzjera (sleeping barber problem)

W zakładzie fryzjerskim znajduje się poczekalnia na N miejsc oraz fotel fryzjerski.
Gdy przychodzi klient to sprawdza czy są wolne miejsca w poczekalni. Jeżeli tak to
zajmuje miejsce, jeżeli nie to przyjdzie on później. Gdy nikogo nie ma i fryzjer śpi to
budzi go.

Z kolei fryzjer patrzy czy są jacyś klienci. Gdy tak to bierze na fotel jednego z
czekających. Gdy nie to zasypia.

background image

10.5 Rozwiązanie problemu producenta i konsumenta za pomocą
komunikatów

Struktura rozwiązania:

1. Zarządzanie buforami leży w gestii procesu administratora
2. Procesy producentów i konsumentów komunikują się z procesem

administratora.

Bufor

P1

P2

Pk

Producenci

K1

K2

Kl

Konsumenci

Admini-

strator

Komunikaty

Komunikaty


Postać komunikatu

#define PROD 1

// Producent

#define KONS 2

// Konsument

#define SERV_NAME "/pserver"

// Nazwa administratora

typedef struct

{

int

type;

/* typ procesu

*/

int

pnr ;

/* numer procesu

*/

pid_t pid;

/* pid procesu

*/

char text[SIZE]; /* tekst komunikatu */

} msg_type;

Proces producenta i konsumenta

main(int

argc,char *argv[])

{

// Lokalizacja administratora
spid = qnx_name_locate(0,SERV_NAME,sizeof(msg),NULL);

for(i=0;i<10;i++) {

msg.type = PROD;
sprintf(msg.text," %s %d - %d",typ_str,nr,i);
res = Send(spid,&msg,&rmsg,sizeof(msg),sizeof(msg));
....

}
exit(0);

}

background image

Administrator zasobu

Problemy:

1. Jak wstrzymać procesy producentów gdy brak miejsca w buforze
2. Jak wstrzymać procesy konsumentów gdy brak elementów w buforze


Rozwiązanie:

1. Procesom które mają być wstrzymane nie udziela się odpowiedzi Reply.
2. Aby można było tak wstrzymany proces potem odblokować należy

przechować jego pid.



Struktury danych

#define MAX_PROC 8

// Maks. liczba oczekujacych procesow

#define BSIZE

2

// Dlugosc bufora komunikatów

// Definicja bufora komunikatow ----
char buffer[BSIZE+1][SIZE]; // Bufor
int bptr;

// Indeks

// Bufor zablokowanych procesow producenta
msg_type prod_buf[MAX_PROC];

// Bufor

int prod_ptr;

// Liczba czek. producentów

// Bufor zablokowanych procesow konsumenta
msg_type kons_buf[MAX_PROC];

// Bufor

int kons_ptr;

// Liczba czek. konsumentów


background image

Proces administratora buforów

main () {

// Rejestracja nazwy administratora
id = qnx_name_attach(0,SERV_NAME);
do {

pid = Receive(0,&msg,sizeof(msg));
if(msg.type == PROD) { // Producent

// Testowanie zajetosci bufora
if(bptr < BSIZE ) { // Jest miejsce – kom. do bufora

wstaw_do_bufora(&msg);

// Mozna zwolnic proces producenta

res = Reply(pid,&msg,sizeof(msg));
// Czy jakis konsument czeka na komunikat ?
if(kons_ptr > 0) { // Tak czeka

pobierz_z_bufora(&msg);
// Usu

ń

konsumenta z kolejki

kons_ptr--;
pid = kons_buf[kons_ptr].type;
// Odblokuj konsumenta
res = Reply(pid,&msg,sizeof(msg));

}

} else { // Brak miejsca w buforze

// Zablokuj producenta w kolejce
msg.pid = pid;
prod_buf[prod_ptr] = msg;
prod_ptr++;

}

}
if(msg.type == KONS) { // Konsument

if(bptr > 0) { // Jest komunikat - mozna pobrac

....
// Czy jakis prod. czeka na miejsce w buforze ?
if(prod_ptr > 0) { // Tak czeka

// Zwalniamy producenta
....

}

} else {

// Brak elementów w buforze

// Zablokuj konsumenta w kolejce

}

} while(1);

}

Szkic działania administratora buforów

background image

10.6 Semafory
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ęć.



Definicja semafora.
Semafor S jest obiektem abstrakcyjnym z którym związany jest licznik L zasobu
przyjmujący wartości nieujemne. Na semaforze zdefiniowane są atomowe operacje
sem_init, sem_wait i sem_post. Podano je w poniższej tabeli.


Operacja Oznaczenie

Opis

Inicjacja
semafora S

sem_init(S,N) Ustawienie licznika semafora S na początkową

wartość N .

Pobranie
jednostki
zasobu

sem_wait(S) Gdy licznik L semafora S jest dodatni (L > 0) zmniejsz

go o 1 (L = L – 1).
Gdy licznik L semafora S jest równy zero (L= 0)
zablokuj proces bieżący.

Zwrot jednostki
zasobu

sem_post(S)

Gdy istnieje jakiś proces oczekujący na semaforze S
to odblokuj jeden z czekających procesów. Gdy brak
procesów oczekujących na semaforze S zwiększ jego
licznik L o 1 (L=L+1).

Definicja operacji wykonywanych na semaforze
Uwaga!
1. Semafor nie jest liczbą całkowitą na której można wykonywać operacje
arytmetyczne .
2. Operacje na semaforach są operacjami atomowymi.

sem_wait(S) {

if(

Licznik L sem. S dodatni

){

Zmniejsz licznik sem. (L=L-1)

} else {

Zawie

ś

proces bie

żą

cy

}

}

sem_post (S) {

if(

Istnieje proc. czekający na zasób

) {

Odblokuj jeden z tych procesów

} else {

Zwi

ę

ksz licznik sem. (L=L+1)

}

}


Niezmiennik semafora
Aktualna wartość licznika L semafora S spełnia następujące warunki:

1. Jest nieujemna czyli: L >= 0
2. Jego wartość wynosi: L= N - Liczba_operacji(sem_wait) +
Liczba_operacji(sem_post). (N jest wartością początkową licznika).

background image

Semafor binarny
W semaforze binarnym wartość licznika przyjmuje tylko dwie wartości: 0 i 1.

Rodzaje semaforów
Wyróżniamy następujące rodzaje semaforów:

1. Semafor ze zbiorem procesów oczekujących (ang. Blocked- set Semaphore) –
Nie jest określone który z oczekujących procesów ma być wznowiony.

2. Semafor z kolejką procesów oczekujących (ang. Blocked- queue Semaphore) –
Procesy oczekujące na semaforze umieszczone są w kolejce FIFO.

Uwaga!
Pierwszy typ semafora nie zapewnia spełnienia warunku zagłodzenia.

background image

10.7 Zastosowania semaforów

10.7.1 Implementacja wzajemnego wykluczania

semaphore S;
sem_init(S,1);

// Deklaracja semafora
// Inicjacja semafora

Proces1 {

do {

Sekcja_lokalna;
sem_wait(S);
Sekcja_krytyczna;
sem_post(S);

} while(1);

}

Proces2 {

do {

Sekcja_lokalna;
sem_wait(S);
Sekcja_krytyczna;
sem_post(S);

} while(1);

}

Przykład zastosowania semafora do ochrony sekcji krytycznej

blokada

sem_wait(s)

użycie zasobu

sem_post(s)

sem_wait(s)

użycie zasobu

sem_post(s)

odblokowanie

P1

P2

L=1

L=0

L=0

L=1


Przebieg operacji blokowania

Wait(S)

Wait(S)

Post(S)

Post(S)

Sekcja

lokalna

Sekcja

lokalna

Sekcja

krytyczna

Sekcja

krytyczna

Proces P1

Proces P2

Rys. 1 Implementacja wzajemnego wykluczania za pomocą semafora – Ilustracja za
pomocą sieci Petriego

background image



10.7.2 Rozwiązanie problemu producenta – konsumenta
.

#define BufSize 8
RecType Buffer[BufSize];
semaphore Mutex;
semaphore Puste;
semaphore Pelne;
int

count;

// Bufor ma 8 elementów
// Bufor na elementy
// Ochrona bufora
// Wolne bufory
// Zajete bufory
// Wska

ź

nik bufora

// Kod w

ą

tku producenta ---------

producent(void) {

RecType x;
do {

...

produkcja rekordu x;
// Czekaj na wolny bufor
sem_wait(Puste);
sem_wait(Mutex);

// Umie

ść

element x w buforze

Buffer[count] = x;
count++;

sem_post(Mutex);
// Pojawił si

ę

nowy element

sem_post(Pelne);

} while(1);

}

// Kod w

ą

tku konsumenta -------

konsument(void) {

RecType x;
do {

// Czekaj na element
sem_wait(Pelne);
sem_wait(Mutex);
// Pobierz element x z bufora

x = Buffer[count];
count--;

sem_post(Mutex);
// Zwolnij miejsce w buforze
sem_post(Puste);
konsumpcja rekordu x;

...

} while(1);

}

main(void) {

count = 0;
sem_init(Puste,BufSize);
sem_init(Pelne,0);
sem_init(Mutex,1);
StartThread(producent,..);
..
StartThread(konsument,..);

..

}

// Inicjacja semafora Puste
// Inicjacja semafora Pelne
// Inicjacja semafora Mutex
// Start K w

ą

tków producenta

// Start L w

ą

tków konsumenta

Rozwiązanie problemu producenta – konsumenta za pomocą semaforów.

background image

10.8 Rozwiązanie problem czytelników i pisarzy za pomocą semaforów

Rozwiązanie z możliwością zagłodzenia pisarzy

- Czytelnik

może wejść do czytelni gdy jest ona pusta lub gdy są tam inni

czytelnicy

- Pisarz

może wejść do czytelni gdy jest ona pusta

Może się tak zdarzyć że zawsze jakiś czytelnik jest w czytelni co doprowadzi do
zagłodzenia pisarzy.

semaphore mutex ;

//

Kontrola dostępu do reader_count

semaphore db;

//

Kontrola dostępu do czytelni

int reader_count;

//

Liczba czytelników w czytelni

Reader(){

while (TRUE) {

sem_wait(mutex);

//

Blokada dostępu do reader_count

reader_count = reader_count + 1;

//

Pierwszy czytelnik blokuje dostęp do czytelni pisarzom

if (reader_count == 1)

sem_wait(db);

//

Zwolnienie dostępu do reader_count

sem_post(mutex);

read_db();

//

Czytelnik czyta

sem_wait(mutex);

//

Blokada dostępu do reader_count

reader_count = reader_count - 1;

//

Gdy nie ma innych czytelników to wpuszczamy pisarzy

if (reader_count == 0)

Sem_post(db);

Sem_post(mutex); //

Zwolnienie dostępu do reader_count

}

Writer() {

while (TRUE) {

create_data();

//

Pisarz zastanawia się

sem_wait(db);

//

Pisarz czeka na dostęp do czytelni

write_db();

//

Pisarz w czytelni - pisze

sem_post(db);

//

Pisarz zwalnia dostęp do czytelni

}

}

main()

{

sem_init(mutex,1);
sem_init(db,1);
....

}

Problem czytelników i pisarzy – rozwiązanie za pomocą semaforów

background image

Rozwiązanie z możliwością zagłodzenia czytelników

- Czytelnik musi czekać gdy są w czytelni lub czekają jacykolwiek pisarze

Rozwiązanie poprawne

- Wpuszczać na przemian czytelników i pisarzy
- Gdy wchodzi jeden z czytelników, to wpuszcza on wszystkich czekających

czytelników


Rozwiązanie poprawne nie dopuszcza do zagłodzenia czy to czytelników czy też
pisarzy.

#define PLACES 8

//

Liczba wolnych miejsc w czytelni

semaphore wolne ;

//

Liczba wolnych miejsc w czytelni

semaphore wr;

//

Kontrola dostępu do czytelni

Reader()
{

while (TRUE) {

sem_wait(wolne);

//

Czekanie na miejsca w czytelni

read_db();

//

Czytelnik w czytelni - czyta

sem_post(wolne);

//

Zwolnienie miejsca w czytelni

}

Writer() {

while (TRUE) {

create_data();

//

Pisarz zastanawia się

sem_wait(wr);

//

Zablokowanie dostępu dla pisarzy

//

Wypieranie czytelników z czytelni

for(j=1;j<=places;j++)

sem_wait(wolne);

write_db();

//

Pisarz w czytelni – pisze

//

Wpuszczenie czytelników

for(j=1;j<= PLACES;j++)

sem_post(wolne);

sem_post(wr);

//

Odblokowanie pisarzy

}

}

main()

{

sem_init(wolne,PLACES);
sem_init(wr,1);
....

}

Rozwiązanie z ograniczoną liczbą miejsc w czytelni

background image

10.9 Rozwiązanie problemy śpiącego fryzjera za pomocą semaforów.

#define MIEJSC 8

//

Liczba wolnych miejsc w poczekalni

semaphore klient ;

semaphore strzyge;

semaphore fryzjer;

int czekaj

ą

cy;

//

Liczba czekających klientów

void klient(int numer) {

while(1) {

sem_wait(mutex);
if(czekajacy < MIEJSC) {

czekajacy++;
sem_post(klient);
sem_post(mutex);
sem_wait(fryzjer);
sem_post(strzyge);

} else

sem_post(mutex);

}

}

void fryzjer(void) {

while(1) {

sem_wait(mutex);

sem_wait(klient);
sem_wait(mutex);
czekajacy--;
sem_post(fryzjer);
sem_post(mutex);
sem_wait(strzyge);

}

}

main(void) {

sem_init(klient,0);
sem_init(fryzjer,0);
sem_init(strzyge,0);
sem_init(mutex,1);

}


background image

wait(klient)

K1

L=1

Fryzjer

post(klient)

wait(fryzjer)

wait(strzyge)

post(fryzjer)

post(strzyge)

wait(fryzjer)

strzyżenie K1

post(klient)

wait(fryzjer)

K2

post(fryzjer)

wait(strzyge)

post(strzyge)

strzyżenie K2

wait(fryzjer)

Rys. 2 Problem śpiącego fryzjera

background image

10.10 Przykład implementacji semaforów
Kolejka Q będzie wskaźnikiem na deskryptor procesu. Oznaczmy ten typ jako:

typedef Queue *DeskryptorProcesu

.

Do implementacji semafora wystarczą dwie operacje:
1.

Suspend(Queue Q)

– Zawieszenie procesu bieżącego w kolejce Q

2.

Resume(Queue Q)

– Odblokowanie pierwszego procesu z kolejki Q.


Typ

Semaphore

będzie zdefiniowany jako wskaźnik na strukturę zawierającą:

- Licznik L semafora.
- Kolejkę

waiting

procesów zablokowanych na danym semaforze.

typedef

structure {

int L;

//

Licznik semafora

Queue waiting;

//

Kolejka proc. oczek na semaforze

} SigRec;

typedef *SigRec Semaphore; // Semafor

Inicjacja semafora
Operacja inicjacji semafora S - sem_init(S,N):

1. Alokacja pamięci na strukturę semafora.
2. Inicjacja pól struktury *S.
3. Inicjacja licznika L semafora na wartość początkową N.

void sem_init(Semaphore S, int N)
{

S = malloc(sizeof(SigRec));

// Alokacja pamięci

S->L = N;

// Inicjacja licznika na N

S->Sem_waiting = NULL;

// Inicjacja kolejki

}

S

L

Waiting

Rys. 3 Semafor jest wskaźnikiem na strukturę

background image


Procedura sem_wait
Kroki procedury sem_wait(S)podane są poniżej:

1. Zablokować przerwania.
2. Zmniejsz licznik L semafora S o 1.
3. Gdy licznik L < 0 to:
- usunąć proces bieżący z kolejki procesów gotowych
- umieścić deskryptor usuniętego procesu w kolejce S->Sem_waiting semafora S
- przekazać sterowanie do systemu operacyjnego
4. Odblokować przerwania.

Operacja musi sem_wait być atomowa. Zablokowanie przerwań jest metodą ochrony
sekcji krytycznej. Pseudokod procedury podano poniżej.

void sem_wait(Semaphore S)
{

Zablokuj_przerwania;
(S->L)--;
if(S->L < 0) { // Czekaj

// Zawie

ś

proces bie

żą

cy w kolejce semafora

Suspend(S->waiting);

}
Odblokuj_przerwania;

}

Przykład 1 Pseudokod procedury semaforowej sem_wait(S)

Ready

Next

PD

Next

PD

NIL

PD

Kolejka procesów gotowych

Proces bieżący

S

Next

PD

Next

PD

NIL

PD

Kolejka procesów czekających na zasób

Semafor

L

Waiting

Suspend(S)

Wskaźnik na

kolejkę

procesów
gotowych

PD - pola

deskryptora

procesu

Rys. 4 Implementacja operacji semaforowej sem_wait(S)

background image


Procedura sem_post
Kroki procedury sem_post(S)podane są poniżej:

1. Zablokować przerwania.
2. Zwiększ licznik L semafora S o 1.
3. Gdy licznik L <= 0 to:
- Usunąć pierwszy proces z kolejki semafora
- Umieścić deskryptor usuniętego procesu w kolejce procesów gotowych.
- Przekazać sterowanie do procedury szeregującej systemu operacyjnego
4. Odblokować przerwania.

Operacja musi sem_post być atomowa. Pseudokod procedury podano poniżej.

void sem_post(Semaphore S)
{

Zablokuj_przerwania;
(S->L)++;

if(S->L <= 0) {

// Są procesy oczekujące na semaforze

// Odblokuj jeden z procesów czekających w kolejce semafora

Resume(S->waiting);

}
Odblokuj_przerwania;

}

Przykład 2 Pseudokod procedury semaforowej sem_post(S)


Ready

Next

PD

Next

PD

NIL

PD

Kolejka procesów gotowych

Proces bieżący

S

Next

PD

Next

PD

NIL

PD

Kolejka procesów czekających na zasób

Semafor

L

Waiting

Wskaźnik na

kolejkę

procesów
gotowych

Resume(S)

Rys. 5 Implementacja operacji semaforowej sem_post(S)

background image


Wyszukiwarka

Podobne podstrony:
Neu Microsoft Word Dokument id Nieznany
Neu Microsoft Word Dokument1
Microsoft Word VAMPIRE ID doc Administrator
Microsoft Word Dokument1 ws25b
Nowy Dokument programu Microsoft Word (5)
Nowy Dokument programu Microsoft Word
Nowy Dokument programu Microsoft Word
Nowy Dokument programu Microsoft Word
Nowy Dokument programu Microsoft Word (2) (1)
Nowy Dokument programu Microsoft Word (5)
Nowy Dokument programu Microsoft Word (11)
nowy dokument programu microsoft word RLKN2HZYOAUUDMOC2OMN5RCBSSHEHKGU4RH67MY
Nowy Dokument programu Microsoft Word

więcej podobnych podstron