Professional Documents
Culture Documents
Signali Semafori I Monitori-Operativni Siste
Signali Semafori I Monitori-Operativni Siste
Signali Semafori I Monitori-Operativni Siste
SEMINARSKI RAD
Mentor: Student:
1. UVOD..........................................................................................................................................3
2. PROBLEM PROIZVOŽAČ – POTROŠAČ KAO ILUSTRACIJA.....................................4
3. KRITIČNA SEKCIJA (Medjusobno Isključivanje)...............................................................5
Softverska realizacija kritične sekcije...........................................................................5
3.1. Algoritam striktne alternacije................................................................................5
3.2. Realizacija kritične sekcije bez stroge alternacije......................................................6
3.3. Dekker-Petersonov algoritam...............................................................................7
3.4. Pekarski algoritam..............................................................................................7
4. HARDVERSKA REALIZACIJA KRITIČNE SEKCIJE.....................................................8
5. SEMAFORI................................................................................................................................9
Upotreba semafora.................................................................................................10
5.1. Realizacija pomoću operativnih sistema(proširena definicija semafora)......................11
6. PROBLEM ZASTOJA I ZAKUCAVANJA..........................................................................12
7. KLASIČNI PROBLEMI SINHRONIZACIJE I SEMAFORA..........................................12
Problem ograničenog bafera.....................................................................................13
7.1. Problem čitalaca i pisaca....................................................................................13
7.2. Problem večere filozofa.....................................................................................14
8. KRITIČNI REGIONI I MONITORI....................................................................................15
Kritični regioni......................................................................................................15
8.1. Monitori.........................................................................................................16
9. MRTVA PETLJA.....................................................................................................................18
9.1. Uslovi za pojavu mrtve petlje.............................................................................18
Tretiranje mrtve petlje.............................................................................................18
10. ZAKLJUČAK........................................................................................................................19
11. LITERATURA.......................................................................................................................20
2
1. UVOD
Svaki računarski sistem sastoji se od konačnog broja resursa. Procesi koriste resurse računarskog
sistema – u slučaju da veći broj procesa želi da koristi isti resurs (npr. deo radne memorije),
operativni sistem mora da obezbedi adekvatne mehanizme sinhronizacije. Ovaj seminarski rad
obuhvata nekoliko mehanizama koji obezbedjuju sinhronizaciju procesa:
Kritične sekcije;
Semafori;
Monitori.
Kooperativni proces može da utiče na druge procese ili da trpi uticaj drugih procesa, a to su svi
procesi koj dele podatke ili bilo kakve resurse. Kooperativni procesi zahtevaju specijalan tretman
i okruženje iz sledećih razloga:
Deljenje informacija – pošto više procesa može biti zainteresovano za iste informacije, na
primer datoteku, mora se obezbediti okrućenje koje će omogućiti pravilan koknkurentni
pristup takvim podacima.
Ubrzavanje rada – ukoliko bi se neki posao podelio na više delova i ako bi se ti delovi
izvršavali konkurentno, ozbiljno bi se poboljšale performanse. Ovo ima smisla samo u
višeprocesorskim sistemima ili višestrukim ulazno-izlaznim kanalima (kao što je slučaj
sa RAID sistemom).
Modularnost – sistemske funkcije mogu modularno da se podele na odvojene procese i
niti.
Pogodnost – korisnik može da obavlja više stvari istovremeno.
Moguća posledica konkuretnog pristupanja zajedničkim podacima jeste nekonsistentsnost tih
podataka. U tom slučaju, promenljive koje formiraju podatak nemaju odgovarajuće vrednosti.
Posmatrajmo dva procesa P1 i P2, koji žele da privremeno sačuvaju neku vrednost na istoj
memorijskoj lokaciji A. Postoji nekoliko mgućih scenarija za ovaj dogadjaj.
1. Proces P1 proverava da li je memorijska lokacija A slobodna. Lokacija A je slobodna.
Proces P1 je obavešten da je lokacija A slobodna.
2. Proces P2 proverava da li je memorijska lokacija A slobodna. Lokacija A je slobodna.
Proces P2 je obavešten da je lokacija A slobodna.
3. Proces P1 upisuje podatak na memorijsku lokaciju A.
4. Proces P2 upisuje podatak na memorijsku lokaciju A.
5. Proces P1 čita POGREŠAN podatak s memorijske lokacije A.
3
2. PROBLEM PROIZVOŽAČ – POTROŠAČ KAO ILUSTRACIJA
4
na sledeći način: najpre se vrednosti promenljive counter upiše u registar procesa, zatim se
vrednost registra inkrementira ili dekrementira i na kraju vrati u promenljivu counter.
Pretpostavimo da je vrednost promenljive counter u početnom trenutku 5, i da proizvodjački i
potrošački proces obavljaju svoje operacije counter++ i counter—konkurentno. Nakon
izvršavanja ovih operacija, vrednost promenljive counter može biti 4,5 ili 6, ali jedina ispravna
vrednost je 5
Kritična sekcija (engl.critical section) deo je koda u kome proces pristupa zajedničkim podacima
kao što su memorijske promenljive, tabele i datoteke – ili ih modifikuje. Svaki operativni sistem
može dozvoliti samo jednom procesu da bude u svojoj kritičnoj sekciji. Dok je jedan proces u
svojoj kritičnoj sekciji, nijedan drugi proces ne sme da udje u svoju kritičnu sekciju. Prema
tome, izvršavanje kritičnih sekcija procesa medjusobno je isključivo u vremenu (engl. mutual
exclusion).
Problem kritične sekcije rešava se definicijom protokola po kome će procesi saradjivati
medjusobno, uz poštovanje pravila medjusobne isključivosti za kritične sekcije. Svaki proces
mora od sistema tražiti dozvolu da udje u kritičnu sekciju. To se obezbedjuje pomoću specijalnog
koda – ulazne sekcije (engl. entry section). Kada prodje ulaznu sekciju, proces može ući u svoju
kritičnu sekciju. Kada je završi, proces mora objaviti svim ostalim procesima da više nije u
kritičnoj sekciji, što se postiže delom koda koji se zove izlazna sekcija (engl. exit section).
Odredjivanja dela programskog koda koji predstavlja kritičnu sekciju zadatak je programera.
Kritična sekcija se može ralizovati:
Softverski;
Hadrverski;
Pomoću semafora;
Pomoću operativnog sistema (sistemskim pozivima);
Višim programskim strukturama za sinhronizaciju (monitorima)
Kritična sekcija se ralizuje softverski, bez pomoći operativnog sistema. Prilikom razvoja
programa ne uzimaju se u obzir pretpostavke o brzini i o broju procesora u sistemu. Algoritam
mora garantovati svakom procesu mogućnost ulaska u svoju kritičnu sekciju.
Pretpostavke softverskog rešenja kritične sekcije su:
Medjusobno isključenje, koje garantuje da se unutar kritične sekcije u jednom trenutku
može naći samo jedan proces;
Proces koji je izvan svoje kritične sekcije ne sme sprečiti druge procese da udju u svoje
kritične sekcije (jedino proces unutar kritične sekcije može sprečiti ostale procese da udju
u kritičnu sekciju)č
Proces ne sme neograničeno dugo čekati da udje u svoju kritičnu sekcuju;
Proces ne sme neograničeno dugo ostati u svojoj kritičnoj sekciji.
5
3.1. Algoritam striktne alternacije
U algoritmu striktne alternacije (engl. strict alternation) zajednička promenljiva turn odredjuje
koji proces može ući u svoju kritičnu sekciju. Samo onaj proces čija je vrednost indeksa jednaka
vrednosti promenljive turn može ući u svoju kritičnu sekciju. Ulazna sekcija je izvedena kao
struktura while koja čeka da promenljiva turn postane jednaka indeksu procesa. Kada proces
udje u svoju kritičnu sekciju i obavi svoje aktivnosti, prelazi se na izlaznu sekciju koja
promenljivoj turn dodeljuje vrednost drugog procesa.
do{
while(turn!=1); //ulazna sekcija
/*kritična sekcija*/
turn =1; //izlazna sekcija
/*ostatak koda*/
}while(1);
Rešenje zadovoljava uslov medjusobnog isključenja (engl. mutual exclusion): samo jedan proces
može da udje u svoju kritičnu sekciju. S druge strane, P1 ne može ući u svoju kritičnu sekciju ako
P0 ne prodje svoju kritičnu sekciju i postavi vrednost promenljive turn na 1, tako da se sistem
može blokirati. Ovde se poštuje stroga alternacija procesa po pitanju ulaska u kritične sekcije, tj.
može se dešavati isključivo sekvenca P0->P1-> P0->P1..... Nedostatak ovog rešenja je tehnika
prozivanja (engl. pooling) ulazne sekcije: stalno se proverava stanje promenljive turn, što troši
procesorsko vreme. Rešenje je nepovoljno u slučaju dva procesa od kojih je jedan znatno sporiji
od drugog. Brži proces će dugo čekati da spori proces dodeli odgovarajuću vrednost
promenljivoj turn i time mu omogućiti ulazak u kritičnu sekciju.
Osnovni nedostatak prethodnog algoritma je sam princip striktne alternacije. Algoritam ne sadrži
dovoljno informacija o procesima – jedina informacija u algroritmu tiče se procesa koji ima
pravo da udje u kritičnu sekciju, bez obzira na to da li želi ili ne. Stroga alternacija se može
eliminisati uvodjenjem binarne promenljive flag za svaki proces posebno. Ako je flag[i]=1,
proces Pi je spreman i želi da udje u svoju kritičnu sekciju. Ako je flag[i]=0, proces Pi ne želi da
udje u svoju kritičnu sekciju, jer njegovo izvršenje trenutno ne zavisi od zajedničkih podataka.
Inicijalno, za dva procesa – P0 i P1 – uvode se dve kontrolne promenljive, flag[0] i flag[1] s
početnom vrednošću 0.
int flag[2];
flag[0]=flag[1]=0; //logicka promenljiva
do{
flag[i]=1;
while(flag[j]); //ulazna sekcija
/*kriticka sekcija*/
flag[i]=0; //izlazna sekcija
}while(1);
Rešenje je, na prvi, pogled korektno, jer zadovoljava medjusobno isključenje, a procesi van
kritičnih sekcija ne utiču jedan na drugog. Proces prvo postavlja svoj indikator (engl.flag) na 1,
što znači da želi da udje u svoju kritičnu sekciju, a zatim proverava da li je drugi proces postavio
6
svoj indikator na 1. Ako jeste, proces čeka u petlji da drugi proces izadje iz svoje kritične sekcije
i postavi svoj indikator na 0. Medjutim i ovo rešenje ima svojih problema:
P0 postavlja flat[0]=1, posle čega se kontrola dodeljuje procesu P1;
P1 postavlja flag[1]=1;
Oba procesa upadaju u beskonačnu petlju, jer su oba indikatora postavljena na 1 i nijedan
ne može da udje u svoju kritičnu sekciju
Dekker-Petersonov algoritam, koje se odnosi na slučaj dva procesa, mora se uopštiti za realan
slučaj sa N procesa u sistemu. Algoritam koji omogućava tu generalizaciju poznat je pod
imenom pekarski algoritam (engl. bakery algorithm). Algoritam se oslanja na poštovanje reda,
čime se sprečava haos (red se poštuje u bankama, poštama, pa i u pekarama). Pravilo je jasno,
7
svaki kupac u pekari dobija broj, a radnik uslužuje kupce redom, počev od onog sa najmanjim
brojem. Slično pravilo primenjuje se i na procese: svakom procesu se dodeljuje broj. Pekarski
algoritam ne garantuje da će dva procesa uvek dobiti različite brojeve. Ako dva procesa dobiju
isti broj, odlučiće ime, tj. indeks procesa (engl. process ID). Pravila pekarskog algoritma su
sledeća:
Sekvenca brojeva se generiše u rastućem redu i dodeljuje procesima (1,2,3,3,4,5,5....);
Procesi se opslužuju na osnovu vrednosti dodeljenih brojeva, počev od procesa kome je
dodeljen najmanji borj;
Ako dva procesa Pi i Pj, dobiju iste brojeve, prvo se opslužuje proces s manjim indeksom
(ako je i<j, tada se prvo opslužuje Pi).
Leksiografski poredak dva elementa (broj, indeks procesa) dobijamo sledećom formulom:
(a,b)<(c,d) ako je a<c ili ako je a=c i b<d
max(a0,....,an-1) je broj ak, takav da je ak≥ai za svako i ϵ [0,n-1].
do{
biranje[i]=1;
broj[i]=max (broj[0],...,broj[n-1])+1;
biranje[i]=0;
for(j=0;j<n;j++){
while(biranje[j]);
while((broj[j] !=0 &&((broj[j],j)<(broj[i],i));
}
/*kriticka sekcija*/
broj[i]=0;
/*ostatak koda*/
}while(1);
Za svaki proces se definiše binarna promenljiva biranje[i], koja služi za sinhronizaciju prilikom
dobijanja broja, i celobrojna promenljiva broj[i],koja sadrži broj koji je proces Pi dobio i koji mu
definiše prioritet. Nijedan proces ne može ući u kritičnu sekciju dok neki proces dobija broj.
Proces Pi najpre dobije broj, a dok dobija broj svi kandidati za ulazak u kritičnu sekciju moraju
da čekaju jer je vrednost biranje[i]=1. Proces Pi dobija najveći broj u tom trenutku, uvećan za 1,
što mu garantuje najniži prioritet. Kada dobije broj, proces P i oslobadja indikator biranje[i]=0 i
pripada ulaznoj sekciji. Proces ostaje u ulaznoj sekciji sve dok ne postane proces sa najmanjim
brojem, to jest s najvišim prioritetom, što se proverava u petlji (broj[j], j) < (broj[i],i)). Proces
zatim ulazi u kritičnu sekciju, a nakon izlaska iz nje, nulira svoj broj i više ne učestvuje u
takmičenju za ulazak u ktitičnu sekciju.
Problem kritične sekcije se u sistemima s jedinim procesorom može rišiti blokadom prekidnih
signala (engl. interrupt disable). U tom slučaju, proces koji udje u kritičnu sekciju ne moće se
prekinuti, pa nema potrebe za sinhronizacijom. To rešenje nije dobro, jer remeti sistemski
časovnik. Kako zabrana i ponovna dozvola prekidnih signala traju dugo, još veći problem se
javlja ukoliko je okruženje višeprocesorsko. To znači da treba naći alternativno rešenje za
realizaciju kritičnih sekcija.
Kritična sekcija može se implementirati na nivou hardvera, ako postoji procesorska instrukcija
koja to podržava. Većina mikropocesora obezbedjuje instrukcije pomoću kojih se moće pročitati
8
i izmeniti memorijska reč ili razmeniti sadržaj dve memorijske reči. Osobina ovih instrukcija je
nedeljivost, tj. atomični način izvršavanja, što znači da se te instrukcije ne mogu prekinuti tokom
izvršavanja.
Naredba TestAndSet(&target) radi sledeće:
čita vrednost korisničke promenljive target;
kopira tu vrednost u korisničku promenljivu rv;
postavlja vrednost promenjive target na true.
Kako je TestAndSet mašinska naredba procesora, ona se izvršava kao jedna operacija koja ne
može biti prekinuta. Operacija TestAndSet garantuje da promenljivama target i rv istovremeno
može pristupiti samo jedan procesor, što znači da se ova operacija ne može paralelno izvršavati
na više procesora. U praksi,rv predstavlja registar procesora, a target memorijsku lokaciju.
Pošto imamo hardversku podršku za realizaciju kritične sekcije, može se koristiti sledeći
algoritam – proces štiti svoju kritičnu sekciju pomoću promenljive lock, čija je inicijalna
vrednost 0.
int lock =0;
do{
while(TestAndSet(lock);
/*kriticna sekcije*/
lock=0;
/*ostatak koda*/
}while (1);
Promenljivoj lock se inicijalno dodeljuje vrednost 0. Prvi proces koji želi da udje u svoju
kritičnu sekciju postavlja vrednost lock na 1 i nastavlja izvršenje, tj.ulazi u svoju kritičnu
sekciju. Prilikom postavljanja vrednosti promenljive lock, proces ne može biti prekinut. Svi
ostali procesi čekaće u petlji while dok je lock=1. Kada proces napusti svoju kritičnu sekciju,
postaviće lock na 0, što će omogućiti drugim procesima da udju u svoju kritičnu sekciju. Hardver
garantuje da nikada dva procesa ne mogu pročitati vrednost lock=0, zato što je operacija
TestAndSet nedeljiva – samo jedan proces može da pročita vrednost promenljive lock i da je
neposredno posle toga postavi na 1.
Instrukcija swap je takodje nedeljva, a obuhvata razmenu vrednosti dve memorijske promenljive
preko privremenog registra procesora. Vrednost promenljive a najpre se upiše u registar temp,
zatim se vrednost promenljive b upiše u promenljivu a, a vrednost registra temp u promenljivu
b, čime a i b praktično razmene vrednosti.1
Pomoću instrukcije swap može se rešiti problem medjusobnog isključivanja. Kôd za sve procese
je:
do{
key=1;
while(key==1) swap(lock,key);
/*kriticna sekcije*/
lock=0;
/*ostatak koda*/
}while (1);
1
Miroslav Hajduković, Operativni sistemi (problemi i struktura) FTN Novi Sad, Novi Sad, 2013.
9
Promenljivoj lock se inicijalno dodeljuje vrednost 0. Prvi proces koji želi da udje u svoju
kritičnu sekciju detektovaće ovu vrednost, a zatim će instrukcijom swap razmeniti vrednosti
promenljivig lock i key (lock=1, key=0). Proces ulazi u svoju kritičnu sekciju. Svi ostali procesi
detektovaće vrednost lock=1 i čekaće da proces napusti svoju kritičnu sekciju i postavi vrednost
promenljive lock na 0. Nakon toga, neki drugi proces može ući u svoju kritičnu sekciju.
5. SEMAFORI
Dosadašnja rešenja nije lako primeniti na kompleksnije slučajeve. U tom kontekstu uvodi se
nova metoda za sinhronizaciju procesa – semafor.
Semafor omogućuje sinhronizaciju niti. Sinhronizacija niti se zasniva na zaustavljanju njihove
aktivnosti, kao i na omogućavanju nastavljanja njihove aktivnosti. Na istom principu se zasniva i
regulacija prolaska vozila kroz raskrsnicu. To daje ideju da se regulisanje prolaska niti kroz
isključivi region može zasnovati na principu mehanizma saobraćajnog semafora. Po analogiji sa
saobraćajnim semaforom, koji reguliše prolaz kroz raskrsnicu, prolaz kroz isključivi region bi
regulisao (softverski) semafor. Ulazak niti u isključivi region bi zavisio od stanja semafora. Ako
stanje semafora dozvoli niti da uđe u kritični region, njen zadatak bi bio da, pri ulasku u
isključivi region, prevede semafor u stanje koje onemogućuje ulazak druge niti u isključivi
region. Ako se takva nit pojavi, njena aktivnost bi se zaustavila pred isključivim regionom, a
njen deskriptor bi se uvezao u listu semafora. Na izlasku iz isključivog regiona, prva nit bi
prevodila semafor u stanje koje omogućuje novi ulazak u isključivi region i omogućavala
nastavak aktivnosti niti koja najduže čeka na ulaz u isključivi region (ako takva niti postoji).
Semafor je celobrojna promenljiva nenegativne vrednosti koja štiti neki resurs i omogućava
komunikaciju izmedju procesa (mehanizam medjusobnog isključivanja ili sinhronizacije
aktivnosti). Vrednost semafora odredjuje se da li je resurs koji taj semafor štiti slobodan. Ako je
vrednost semafora val(s)=0, resurs je zauzet. Resurs je slobodan ukoliko je vrednost semafora
val(s)>0. Svaki semafor ima svoju početnu vrednost, a nad njim se mogu izvršiti dve nedeljive
operacije, koje su radi jednostavnosti predstavljene kao signal(s) i wait(s). nedeljivost ovih
operacija ogleda se u sledećim činjenicama:
signal i wait se ne mogu podeliti na više ciklusa;
dva procesa ne mogu istovremeno izvršavati ove operacije nad istim semaforom.
Kao što je rečeno operacija wati(s) dekrementira vrednost semafora samo ako je s>0. Uslučaju
da je s=0, proces koji izvršava ovu operaciju čeka da vrednost semafora postane pozitivna (tj. da
drugi proces izvrši operaciju signal nad semaforom), nakon čega će dekrementirati vrednost
semafora.
Operacija signal(s) inkrementira vrednost semafora. Simbolički, operacije signal i wait mogu se
predstaviti na sledeći način:
wait(s): when(s>0) do decrement s;
signal(s): increment s;
Upotreba semafora
Problem kritične sekcije može se rešiti upotrebom binarnog semafora mutex čija je inicijalna
vrednost 1:
semaphore mutex;
do{
wait(mutex);
10
/*kriticna sekcije*/
signal(mutex);
/*ostatak koda*/
}while (1);
Ulazna sekcija svih procesa razrešava se operacijom wait. Samo jedan proces proći će semafor
mutex, oboriti mu vrednost na 0 i ući u svoju kritičnu sekciju. Svi drugi procesi čekaju na
semaforu. Kada proces napusti kritičnu sekciju, oslobodiće semafor komandom signal (mutex).
Saradnju izmedju procesa čije su aktivnosti sinhronizovane obezbedjuje semafor proceed čija je
inicijalna vrednost 0. Mehanizam sinhronizacije možemo prikazati sledećim primerom:
Posmatraju se dva procesa P1 i P2. Procesu P1 je u tački S1 neophodna informacija koju proces
P2 obezbedjuje u tački S2. Proces P1 ne može da nastavi dalje izvršenje u tački S1 dok proces P2
ne prože tačku S2 i ne obezbedi neophodju informaciju.
Osnovni nedostaci softverske i hardverske realizacije navedene metode zaštite kritične sekcije
semafora su:
ignosiranje prioriteta procesa – može se desiti da proces najvišeg prioriteta udje u kritičnu
sekciju tek posle mnoštva neprioritetnih procesa;
mogućnost da proces bude zauzet čekanjem (engl. busy waiting). Do ove pojave dolazi
ukoliko se proces neprestano vrti u petlji while i ne radi ništa korisno, već samo
proverava vrednost neke promenljive kako bi saznao da li može ući u svoju kritičnu
sekciju ili ne. Iako ne radi ništa korisno, proces troši procesorsko vreme. Kako se u
kritičnoj sekciji u jednom trenutku može naći samo jedan proces, veliki broj procesa koji
čeka na ulazak u kritičnu sekciju opteretiće procesor. Posmatrajmo situaciju sa 1000
procesa od kojih se jedan nalazi u kritičkoj sekciji, a ostali čekaju na ulazak u svoje
kritične sekcije. To znači da imamo jedan proces koji radi nešto korisno i 999 procesa
koji čekajući troše procesorsko vreme.
Ovi nedostaci se mogu izbeći ukoliko se kritična sekcija realizuje pomoću sistemaskih poziva
kojima se proces može blokirati. Proces koji čeka da udje u kritičnu sekciju postaje blokiran
(engl. blocked), sve dok ga neki drugi proces ne oslobodi blokade. U kontekstu semaforskih
tehnika, proces koji čeka na semaforu čija je vrednost 0 blokira se i ne troši procesorsko vreme.
Da bi rešili ovaj problem potrebno je da se operacije wait i signal redefinišu. Ideja je da se za
svaki semafor uvede poseban red čekanja (semaforski red). Svi procesi koji izvršavaju operaciju
wait nad semaforom čija je vrednost negativna ili jednaka nuli (val(s)≤0) pomoću sistemskog
poziva sleep blokiraju se i prevode u semaforski red. Procesor se oslobadja i predaje nekkom
drugom proesu koji nije blokiran. Proces nastavlja svoje izvršenje nakon sistemskog poziva
wakeup, koji ukida blokadu procesa. Blokada se može ukinuti samo ako je proces prvi u
semaforskom redu ili ima najviši prioritet na semoforu, a neki drugi proces obavi operaciju
signal nad tim semaforom.
U proširenom kontekstu semafor se definiše kao struktura čiji su elementi celobrojna vrednost
semafora (koja može biti i negativna) i lista pokazivača na procese koji čekaju na semafor.
typedef struct{
int value;
struct process *L;
}semaphore;
11
Vrednosti semafora S može biti:
val(s)>0 (resurs je slobodan);
val(s)=0 (resurs je zauzet, ali je semaforski red slobodan);
val(s)<0 (resurs je zauzet, u semaforskom redu postoje proesi koji čekaju na taj semafor);
operacija wait dekrementira vrednost semafora i – ako je ona nakon toga negativna – stavlja
proces u semaforski red i blokira proces:
wait(S){
S.value--;
If(S.value<0){
sleep();
}
}
Operacija signal inkrementira vrednost semafora i – ako je ona posle toga negativna ili jednaka
nuli – uklanja jedan od procesa iz liste(izvršava sistemski poziv wakeup i prebacuje proces u red
čekanja za spremne procese):
Signal(S){
S.value++;
If(S.value<=0)
wakeup();
}
12
Zakucavanje (engl.starvation) nastaje kada procesi beskonačno dugo čekaju u semaforskom
redu. Ova situacija je moguća ukoliko se procesi iz semaforskog reda uklanjaju po principu
LIFO(Last In First Out).
13
signal (bafer_spreman);
signal(slobodno_mesot);
}while(1);
Konkurentni procesi mogu da dele objekte podataka. U zavisnosti od toga šta procesi žele da
rade s podacima, izdavamo sledeće kategorije procesa:
procese čitaoce(engl.readers), koji ćele samo da čitaju deljive objekte;
procese pisce(writers), koji žele da menjaju sadržaj objekata.
Dva procesa čitaoca mogu istovremeno da čitaju sadržaj deljenog objekta, dok proces koji piše
ne sme dozvoli9ti konkurentni pristup deljenom objektu. To znači da dva pisca ne mogu
istovremeno da menjaju sadržaj zajedničkog objekta i da nema čitanja dok pisac ne obaci svoje
aktivnosti. Za razliku od bafera koji ima N elemenata, ovde je reč o jednom objektu, čiji se
sadržaj čita ili modifikuje.
Ovaj problem se može rešiti pomoću dva mutex semafora:
upis, koji služi za medjusobno isključenje procesa pisaca i čitalaca;
moguća_izmena, koji obezbedjuje medjusobno isključenje pristupa kontrolnoj
promenljivoj broj_čitalaca(promenljiva broj_čitalaca čuva informaciju o broju aktivnih
čitalaca).
Pet filozofa sede za okruglim stolom. Ispred svakog filozofa nalazi se po jedan tanjir sa
špagetama. Izmedju svaka dva tanjira postavljena je po jedna viljuška. Filozofi su svoj život
posvetili razmišljanju. Ako ogladne oni jedu špagete, pa ponovo razmišljaju. Problem je u
sledećem: da bi neki filozof mogao jesti potrebne su mu dve viljuške. Zato, kada filozof ogladni,
najpre pogleda da li može uzeti obe viljuške i ako može, onda jede (za to vreme njegvi susedi ne
mogu jesti). Ako ne može, filozof razmišlja i čeka dok obe viljuške ne postanu slobodne. Kada
završi jelo, filozof spušta obe viljuške i nastavlja da razmišlja.
14
Ovaj problem se može rešiti na sledeći način:
svaki filozof predstavlja proces, a svaka viljuška semafor.
Definišu se zajednički podaci – 5 semafora kojima se štite viljuške.
semaphore viljuska [5];
filozof (i){
do{
wait(viljuska[i])
/*filozof jede*/
wait(viljuska[(i+1)%5])
signal(viljuska[i]);
signal(viljuska[(i+1)%5]);
/*filozof razmislja*/
}while (1);
Rešenje je dobro samo na prvi pogled – zastoj je moguć ako svi filozofi ogladne odjedanput i
uzmu viljušku s leve strane. Tada niko neće razrešiti drugu operaciju wait, tj. niko neće doći do
druge viljuške. Zastoj se može sprečiti ukoliko se:
dozvoli da najviše četiri filozofa sednu za sto;
dozvoli da filozof uzme vuljuške samo ako su obe slobodne;
koriste asimtrična rešenja – na primer, da neprani filozovi (prvi, treci, peti) uzmu prvo
viljuške sleva a zatim zdesna, a parni (drugi i četvrti), prvo viljuške zdesna pa sleva.
Iako su semafori dobro rešenje problema sinhronizacije procesa, ozbiljne greške koje nehotično
može napraviti programer mogu izazvati zastoj u sistemu. Npr. programer može nehotično
zameniti redosled operacija signal i wait nad semaforom koji štiti kritičnu sekciju.
U ovakvoj situaciji veći broj procesa moći će da udje u svoje kritične sekcije istovremeno, što je
protivno principu medjusobnog isključenja. Programer, takodje, može zameniti jednu operaciju
drugom.
Kritični regioni
8.1. Monitori
Monitori su takodje konstrukcije visokog nivoa koja služi za sinhronizaciju. Oni omogućavaju
programeru da resurse posmatra kao objekte (struktura monitora podseća na instance klase u
OOP). Svaki monitor se sastoji od:
promenljivih koje opisuju deljeni resurs, tj. objekat, čije vrednosti definišu stanje
monitora. Lokalne promenljive su vidljive samo unutar monitora;
skup procedura i funkcija kojima se pristupa objektu, tj. promenljivama monitora;
dela programa koji inicijalizuje objekat, a koji se izvršava samo jednom, prilikom
stvaranja objekta.
Konstrukcija monitora rešava problem sinhronizacije, tj. dozvoljava da samo jedan proces bude
aktivan u monitoru.
Jednostavan bafer koji se koristi prilikom rešavanja problema proizvodjač-potrošač, može se
predstaviti monitorom koji čine:
baferski prostor i pokazivači na prvo slobodno i prvo zauzeto mesto;
procedure za dodavanje elemenata u bafer i uzimanje elemenata iz bafera;
procedure za inicijalizaciju pokazivača na početak bafera.
Ukoliko su potrebni dodatni sinhronizacioni mehanizmi, programer mora sam da definiše
promenljive kojima će dodatni problem rešiti. Kada je dodatni sinhronizacioni mehanizam neka
uslovna konstrukcija, definišu se tzv. uslovne promenljive:
condition x,y;
Jedine operacije koje mogu da se izvode nad ovim promenljivama jesu signal i wait. Operacija
x.wait() blokiraće proces koji je tu operaciju pozvao. Operacija x.signal ukinuće blokadu sa
tačno jednog blokiranog procesa. Ako nema blokiranih procesa, operacija signal ne radi ništa, za
razliku od operacije signal na semaforu, koja uvek inkrementira vrednost.
Ulazni red
x
y
Inicijalizacija objetka
Problem večere filozofa možemo rešiti uspešno pomoću monitora. Najpre se definiše struktura
podataka stanje, koja predstavalja trenutno stanje filozofa. Svaki filozof se može naći u jednom
od sledeća tri stanja: razmišlja, gladan je, jede. Kada razmišlja, ne treba mu ništa; kada je gladan,
pokušava da jede, a ne razmišlja. Filozof može da jede samo ako njegovi susedi ne jedu.
Dodatno, uvode se i uslovne promenljive stanje[i] koje će blokirati filozofa ukoliko je gladan, a
ne može da uzme obe viljuške.
monitor dp{
enum{misli, gladan, jede} stanje[5];
condition filozof[5];
void pickup(int i){
stanje[i]=gladan;
test[i];
if(stanje[i]!=jede) filozof[i].wait();
}
void release(int i){
stanje[i]=misli;
test((i+4)%5);
test((i+1)%5);}
void test(int i){
if((stanje[i]==gladan)&&(stanje[i+4)%5]!=jede)&&(stanje i+1)%5!=jede)) {
stanje[i]=jede;
filozof[i].signal();}
}
void init(){
for (int i=0; i<5;i++)
stanje[i]=misli;
}
}
Najpre se u monitoru svi filozofi dovedu u stanje misli – dakle svi razmišljaju, niko nije gladan –
niko ne jede. Svaki filozof mora obaviti sledeće operacije:
dp.pickup(i);
/* filozof jede*/
dp.release(i);
Svaki filozof, pre nego što počne jesti, mora da pozove proceduru pickup iz monitora dp.
Uokviru te procedure, filozof će doći do obe viljuške ili će biti blokiran operacijom
filozof[i].wait. Ako uzme obe viljuške, filozof jede, a zatim ih spusti na sto. Posle toga, poziva
se procedura release, koja oslobadja obe viljuške, a po potrebi i blokirane filozofe.
17
9. MRTVA PETLJA
Mrtva petlja opisuje situaciju u kojoj je trajno zaustavljena aktivnost međusobno zavisnih
procesa. Na primer, to se desi kada dva procesa žele da u režimu međusobne isključivosti
pristupaju dvema datotekama. Ako prvi od njih otvori prvu datoteku, a zatim drugi od njih otvori
drugu datoteku, tada nema mogućnosti za nastavak aktivnosti tih procesa, bez obzira da li je
sistemska operacija otvaranja blokirajuća ili ne. U slučaju blokirajućih sistemskih operacija
otvaranja, pokušaj prvog procesa da otvori drugu datoteku dovodi do trajnog zaustavljanja
njegove aktivnosti.Isto se dešava sa drugim procesom prilikom njegovog pokušaja da otvori prvu
datoteku. Zaustavljanje aktivnosti ova dva procesa je trajno, jer je svaki od njih zauzeo datoteku
koja treba onom drugom procesu za nastavak njegove aktivnosti i nema nameru da tu datoteku
oslobodi. U slučaju neblokirajuće sistemske operacije otvaranja, procesi upadaju u beskonačnu
petlju (starvation), pokušavajući da otvore datoteku, koju je isključivo za sebe već otvorio drugi
proces. Ovakav oblik međusobne zavisnosti procesa se naziva i živa petlja (livelock). Ona se, po
svom ishodu, suštinski ne razlikuje od mrtve petlje.
Pojava mrtve petlje je vezana za zauzimanje resursa, kao što su, na primer, prethodno pomenute
datoteke. Pri tome, za pojavu mrtve petlje je potrebno da budu ispunjena četiri uslova:
zauzimani resursi se koriste u režimu međusobne isključivosti,
resursi se zauzimaju jedan za drugim, tako da proces, nakon zauzimanja
izvesnog broja resursa, mora da čeka da zauzme preostale resurse,
resurse oslobađaju samo procesi koji su ih zauzeli i
postoji cirkularna međuzavisnost procesa (prvi proces čeka oslobađanje
resursa koga drži drugi proces, a on čeka oslobađanje resursa koga drži treći
proces, i tako redom do poslednjeg procesa iz lanca procesa, koji čeka
oslobađanje resursa koga drži prvi proces).
Tretiranje mrtve petlje
Postoje četiri pristupa rešavanja problema mrtve petlje:
sprečavanje (prevention) pojave mrtve petlje (onemogućavanjem važenja
nekog od četiri neophodna uslova za njenu pojavu),
izbegavanje (avoidance) pojave mrtve petlje
otkrivanje (detection) pojave mrtve petlje i oporavak (recovery) od nje i
ignorisanje problema mrtve petlje.
Kod sprečavanja pojave mrtve petlje, važenje prvog uslova nije moguće sprečiti, ako je
neophodno korišćenje resursa u režimu međusobne isključivosti. Važenje drugog uslova se može
sprečiti, ako se unapred zna koliko treba resursa i ako se oni svi zauzmu pre korišćenja. Pri tome,
neuspeh u zauzimanju bilo kog resursa dovodi do oslobađanja prethodno zauzetih resursa, što je
moguće učiniti bez posledica, jer nije započelo njihovo korišćenje. Važenje trećeg uslova se
može sprečiti, ako postoji način da se zauzeti resurs privremeno oduzme procesu. I konačno,
važenje četvrtog uslova se može sprečiti, ako se resursi uvek zauzimaju u unapred određenom
redosledu, koji isključuje mogućnost cirkularne međuzavisnosti procesa.Izbegavanje pojave
mrtve petlje zahteva poznavanje podataka (1) o maksimalno mogućim zahtevima za resursima,
(2) o ukupno postavljeni zahtevima za resursima i (3) o stanju resursa. Podrazumeva se da se
udovoljava samo onim zahtevima za koje se proverom ustanovi da, nakon njihovog usvajanja,
postoji redosled zauzimanja i oslobađanja resursa u kome se mogu zadovoljiti maksimalno
mogući zahtevi svih procesa.
18
10. ZAKLJUČAK
Praktična vrednost ovoga pristupa nije velika, jer se obično unapred ne znaju maksimalno
mogući zathevi procesa za resursima, a to je neophodno za proveru da li se može udovoljiti
pojedinim zahtevima. Sem toga, ovakva provera je komplikovana, a to znači i neefikasna.
Otkrivanje pojave mrtve petlje se zasniva na sličnom pristupu kao i izbegavanje pojave mrtve
petlje. U ovom slučaju se proverava da li postoji proces, čijim zahtevima se ne može udovoljiti
ni za jedan redosled zauzimanja i oslobađanja resursa. Pored komplikovanosti ovakve provere,
problem je i šta učiniti, kada se i otkrije pojava mrtve petlje. Ako se resursi ne mogu privremeno
oduzeti od procesa, preostaje jedino uništavanje procesa, radi oslobađanja resursa koje oni drže.
Međutim, to nije uvek prihvatljiv zahvat. Zbog toga ni ovaj pristup nema veliki praktični značaj.
Ignorisanje problema mrtve petlje je pristup koji je najčešće primenjen u praksi, jer se ovaj
problem ne javlja tako često da bi se isplatilo da ga rešava operativni sistem. Prema tome, kada
se mrtva petlja javi, na korisniku je da se suoči sa ovim problemom i da ga reši na način, koji je
primeren datim okolnostima.
19
11. LITERATURA
20