Signali Semafori I Monitori-Operativni Siste

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 20

ALFA BK UNIVERZITET

FAKULTET ZA MATEMMATIKU I RAČUNARSKE NAUKE


STUDIJSKI PROGRAM: RAČUNARSKE NAUKE

SEMINARSKI RAD

SIGNALI, SEMAFORI, MONITORI


UPOTREBA SINHRONIZACIJE PROCESORA

Mentor: Student:

Dejan Đukić Asmir Pljakić

Novi Pazar, 2018. god.


SADRŽAJ

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.

Da bi se izbegle slične situacije, operativni sistem mora da obezbedi mehanizme za očuvanje


konsistentnosti podataka, to jest mehanizme konkurentnog izvršavanja procesa.

3
2. PROBLEM PROIZVOŽAČ – POTROŠAČ KAO ILUSTRACIJA

Konkurentno izvršavanje kooperativnih procesa zahteva mehanizam koji će dozvoliti procesima


da komuniciraju izmedju sebe i da sinhronizuju svoje akcije. Problem sinhronizacije se može
objasniti na čuvenom odnosu proizvodjač – potrošač (engl. producer – consumer) koji
predstavlja zajedničku paradigmu kooperativnih procesa. Proizvodjač je proces koji proizvodi
informacije, a potrošač je proces koji ih troši, to jest koristi. Ta dva procesa mogu da rade
konkurentno, ukoliko postoji bafer koji će puniti proizvodjač, a prazniti potrošač. Pravila
sinhronizacije su sama po sebi jasna: potrošač ne može uzeti ništa iz bafera ukoliko proizvodjač
to prethodno nije stavio u bafer.
Bafer takodje nameće svoja pravila. U idealnom slučaju, bafer je beskonačnog kapaciteta (engl.
unbounded buffer), tj. ima beskonačan broj mesta i nikada se ne može napuniti. Ovakav slučaj u
praksi ne postoji. Kapacitet realnih bafera ograničen je na N elemenata, tj. informacija (engl.
bound buffer). Ograničenjem kapaciteta uvodi se nov limit, tj. novo pravilo singronizacije:
ukoliko je bafer pun, proizvodjač ne može ubaciti informaciju dok potrošač najpre ne uzme nešto
iz bafera.
Bafer se pod operativnim sistemom može ralizovati na dva načina:
 Interprocesnom komunikacijom;
 Pomoću deljive memorije.
item buffer [N]
int in=0;
int out=0;
int counter=0;
Proizvodjač:
item sledeci_proizveden;
while (1){
while (counter==N)
buffer[in]=sledeci_proizveden;
in=(in+1)%N;
counter++;
}
Potrošač:
item sledeci_potrosen;
while (1){
while (counter==0)
buffer[out]=sledeci_potrosen;
out=(out+1)%N;
counter--;
}
Ovde imamo kôd za realizaciju bafera punim kapacitetom. Definišemo bafer veličine N,
promenljive in i out koje nam služe da označimo prvo slobodno i prvo zauzeto mesto u baferu, i
promenljiva counter koja služi za praćenje broja zauzetih mesta. Promenljiva counter se
inkrementira svaki put kada se ubaci nov element u bafer, a dekrementira kad god potrošač uzme
jedan element iz bafera.
Nekorektne situacije nastaju kao posledica implementacije operacija inkrementiranja i
dekrementiranja promenljive counter. Po pravilu, operacije counter++ i counter--izvršavaju se

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

3. KRITIČNA SEKCIJA (Medjusobno Isključivanje)

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)

Softverska realizacija kritične sekcije

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.

3.2. Realizacija kritične sekcije bez stroge alternacije

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

3.3. Dekker-Petersonov algoritam

Kombinacijom prethodnih rešenja, Dekker i Peterson definisali su prihvatljivo softversko rešenje


kritične sekcije, zasnovano na promenljivama turn i flag. Promenljiva flag ukazuje na to da
proces želi da udje u svoju kritičnu sekciju, dok promenljiva turn uredjuje proces koji ima
prednost pri ulasku i time obezbedjuje mehanizam medjusobnog isključenja. Proces P i najpre
nastavlja vrednost promenljive turn na j (turn=j), to jest daje šansu drugom procesu (Pj) da udje
u svoju kritičnu sekciju. Proces Pi čeka na ulazak u kritičnu sekciju samo ako su ispunjeni sledeći
uslovi:
 proces Pj želi da udje u svoju kritičnu sekciju (flag[j] = 1);
 procesu Pj data je šansa za ulazak u kritičnau sekciju (turn=j).
U svim drugim situracijama proces Pi ulaz u svoju kritičnu sekciju. I to se postiže na sledeći
način:
do{
flag[i]=true;
turn = j;
while (flag[i] && turn=j){
/*kriticka sekcija*/
}
flag[i]=0;
/*ostatak koda*/
} while (1);
Svi uslovi su zadovoljeni:
 Poštuje se medjusobno isključenje: zahvaljujući pomoćnoj promenljivoj turn, u kritičnu
sekciju će ući samo jedan proces, i to onaj koji ima prednost. Proces koji nema prednost
ne odustaje, ali čeka red.
 Nema striktne alternacije: neka se P1 zaglavi u ostatku koda koji ne pripada kritičnoj
sekciji dovoljno dugo, tako da proces P0 krene da izvršava petlju do-while iz početka.
Tada je flag[1]=0, flag[0]=1, turn=1. Vrednost logičkog izraza petlje while procesa P 0
biće 0, što znači da proces P0 može ponovo ući u kritičnu sekciju, ne čekajući proces P1.
 Nema zaglavljivanja u beskonačnoj petlji jer ne može biti istovremeno turn=0 i turn=1, tj.
ne postoji mogućnost da oba procesa beskonačno dugo ostanu unutar petlje while.

3.4. Pekarski algoritam

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.

4. HARDVERSKA REALIZACIJA KRITIČNE SEKCIJE

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.

5.1. Realizacija pomoću operativnih sistema(proširena definicija semafora)

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();
}

6. PROBLEM ZASTOJA I ZAKUCAVANJA

U višeprocesorskom okruženju, više procesa se mogu medjusobno takmičiti za konačan broj


resursa. Kada proces zahteva resurs, a resurs nije raspoloživ, proces ulazi u stanje čekanja na
resurs (wait) i blokira se. Blokirani proces može zauvek ostati u tom stanju ukoliko potrebni
resurs ostane neraspoloživ. Ova situacija je moguća ukoliko je resurs prethodno dodeljen na
korišćenje drugom procesu koji tokom vremena takodje prelazi u stanje čekanja na drugi
neraspoloživ resurs.
Loša implementacija semafora može dovesti do situacije u kojoj jedan ili više procesa
beskonačno dugo čekaju na dogadjaje koji se nikada neće dogoditi. Takvi procesi se nalaze u
stanju koje se zove zastoj (engl. deadlock, deadly embrace). Ovakva pojava je sasvim moguća,
osobito pri radu sa savremenim višenitnim procesima.
Neka su P0 i P1 procesi koji redom izvršavaju sledeće operacije nad semaforima S i Q čije
su inicijalne vrednosti 1:
Proces P0 Proces P1
wait(S) wait(Q)
wait(Q) wait(S)
... ...
signal(S) signal(Q)
signal(Q) signal(S)
Ova sekvenca dogadjaja dovešće do zastoja. Kada proces P0 izvrši operaciju wait(S), vrednost
semafora S postaje 0, a to se isto dešava i sa semaforom Q, čiju će vrednost P 1 postaviti na 0.
Procesi P0 i P1 naći će se nakon toga u stanju zastoja: P 0 čeka na semaforu Q, čiju vrednost može
uvećati proces P1 narednom signal(Q), jer čeka na semoforu S, čiju vrednost može da uveća
proces P0. Nijedna signalna operacija neće se izvršiti, jer oba procesa čekaju na semaforima.

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).

7. KLASIČNI PROBLEMI SINHRONIZACIJE I SEMAFORA

Primena semaforskih tehnika moguća je u rešavanju sledećih problema:


 proizvodjač – potrošač (problem ograničenog bafera);
 problem čitalaca i pisaca;
 problem večere filozofa.

Problem ograničenog bafera

Sledeći primer ilustruje rešavanje problema proizvodjač – potrošač upotrebom semaforskih


tehnika. Sinhronizacija se obezbedjuje sledećim brojačkim semaforima, čije vrednosti pripadaju
intervalu[0,N-1], gde je N kapacitet bafera:
 item_available (potrošač ne može uzeti ništa iz bafera ukoliko proizvodjač to prethodno
nije stavio u bafer);
 space_available (ako je bafer pun, proizvodjač ne može ubaciti informaciju).
Takodje uvešćemo mutex semafor bafer_spreman kojim se bafer štiti kao nedeljvi resurs. Na taj
način se sprečava mogućnost sabune s pokazivačima koja nastaje ukoliko jedan proces čita
informacije iz bafera, dok drugi proces nešto upisuje u bafer.
U sledećem tekstu data je realizacija ovog problema:
typedef struct{}item;
item buffer[N];
int in=0;
int out=0;
//inicijalizujemo semafor
podatak_spreman=0;
slobodno_mesto=N;
bafer spreman=j;
//proizvodjac
do{
item sledeci_proizveden;
wait(slobodno_mesto);
wait(bafer_spreman);
buffer[in]=sledeci_proizveden;
in=(in+1)%N;
signal(bafer_spreman);
signal(podatak_spreman)
}while(1);
//potrosac
do{
item sledeci_potrosen;
wait(podaak_spreman);
wait(bafer_spreman);
sledeci_potrosen=buffer[out];
out=(out+1)%N;

13
signal (bafer_spreman);
signal(slobodno_mesot);
}while(1);

7.1. Problem čitalaca i pisaca

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).

Inicijalne vrednosti semafora i promenljive broj_čitalaca su: moguća_izmena=1,upis=1,


broj_čitalaca=0.
wait(upis);
signal(upis);
wait(moguca_izmena);
broj_citalaca++;
if (broj_citalaca==1) wait(upis);
signal(moguca_izmena);
wait(moguca_izmena);
broj_citalaca--;
if (broj_citalaca==0) signal(upis);
signal(moguca_izmena);
proces čitalac proverava koliko ima aktivnih čitalaca u sistemu, a pomoću semafora moguća-
_izmena kontroliše promenljivu broj_čitalaca. Ukoliko je vrednost promenljive broj_čitalaca
nakon inkrementiranja jednaka 1, on je jedini čitalac i mora eventualno sačekati na pisca
wait(upis). U protivnom, on nije prvi i može slobodno da čita . proces završava čitanje i
dekrementira vrednost promenljive broj_čitalaca. Ako ječitalac poslednji ili jedini, izvršiće
operaciju signal(upis) i time osloboditi objekat za pisce.

7.2. Problem večere filozofa

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.

8. KRITIČNI REGIONI I MONITORI

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

Opisane greške se mogu izbeći korišćenjem konstrukcija karakterističnih za višeprogramske


jezike, koji se nazivaju kritični regioni(engl. critical regions) ili uslovni kritini regioni (engl.
conditional critical regionals) . Osim njih definisana je i fundamentalna konstrukcija za
sinhronizaciju procesa – monitor.
Kritični region zahteva promenljivu v tipa T, koja je zajednička za veći broj procea, što se
simbolički obeležava:
 v: shared T;
Promenljivoj v može se pristupati samo unutar regiona naredaba S, uslovno, sa sledećom
sintaksom:
 region v when (B) S;
Ova konkstrukcija znači dok se naredba S izvršava, nijedan proces neće pristupati promenljivoj
v. Logički izraz B upravlja radom u kritičnom regionu. Kada proces udje u kritični region, izraz
B se ispisuje i – ukoliko je tačan – naredba S se izvršava. Ako izraz nije tačan, medjusobno
15
isključenje se napušta i odlaže, dok B ne postane tačan.Kritični regioni štite od grubih,
nehotičnih programerskih grešaka u sinhronizaciji.
Problem ograničenog bafera se može rešiti uz pomoć kritičnih regiona:
struct buffer{
int pool[n];
int count, in, out;
}
//kod za proizvodjacki proces
Region buffer when (count<n){
pool[in]=sledeci_proizveden;
in=(in+1)%n;
coutn++;

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

redovi povezani sa x i y uslovima


deljive promenljive
Procedure / funkcije 16

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

9.1. Uslovi za pojavu mrtve petlje

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

1) Borislav Đorđević, Dragan Pleskonjić, Nemanja Maček, Operativni Sistemi UNIX i


Linux
2) Borislav Đorđević, Dragan Pleskonjić, Nemanja Maček, Operativni Sistemi – Teorija,
praksa i rešeni zadaci
3) Miroslav Hajduković, Operativni sistemi (problemi i struktura) FTN Novi Sad, Novi
Sad, 2013.

20

You might also like