Upload
wyman
View
72
Download
2
Embed Size (px)
DESCRIPTION
Synchroniz ácia procesov. Background. Súbežný prístup k zdieľaným dátam môže viesť k ich nekoexistencii Zabezpečenie koexistencie dát pri vzájomnej spolupráci procesov si vyžaduje zaoberať sa mechanizmami synchronizácie prístupu k zdieľaným dátam - PowerPoint PPT Presentation
Citation preview
©2009Operačné systémy
Synchronizácia procesov
6.2 ©2009Operačné systémy
Background
Súbežný prístup k zdieľaným dátam môže viesť k ich nekoexistencii
Zabezpečenie koexistencie dát pri vzájomnej spolupráci procesov si vyžaduje zaoberať sa mechanizmami synchronizácie prístupu k zdieľaným dátam
Predpokladajme že chceme poskytnúť riešenie problému konzument – producent ktorý zapĺňa všetky „buffers“. Môžeme to urobiť na základe počítadla celého čísla, ktoré uchováva počty plných „buffers“. Najprv je počítadlo (premenná count) nastavené na 0. Zaznamenáva prírastok od producenta, ktorý vytvorí nový bufer. Stav počítadla sa znižuje v dôsledku činnosti konzumenta, ktorý spotrebuje bufer.
6.3 ©2009Operačné systémy
Producent
while (true) {
/* produce an item and put in nextProduced */
while (count == BUFFER_SIZE)
; // do nothing
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
count++;
}
6.4 ©2009Operačné systémy
Konzument
while (true) {
while (count == 0)
; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
/* consume the item in nextConsumed
}
6.5 ©2009Operačné systémy
Súbeh
(count++) implementované môže byť nasledovne
register1 = count register1 = register1 + 1 count = register1
count-- implementované môže byť nasledovne
register2 = počítadlo register2 = register2 - 1 počítadlo = register2
Uvažujme toto vykonanie vložením “count = 5” prvotne:
S0: producent vykonáva register1 = count {register1 = 5}S1: producent vykonáva register1 = register1 + 1 {register1 = 6} S2: konzument vykonáva register2 = count {register2 = 5} S3: konzument vykonáva register2 = register2 - 1 {register2 = 4} S4: producent vykonáva count = register1 {count = 6 } S5: consumer execute count = register2 {count = 4}
6.6 ©2009Operačné systémy
Riešenie problému kritickej sekcie
1. Vzájomné vylúčenie – Ak proces Pi je vykonávaný v jeho kritickej sekcii, potom žiadny iný proces nemôže vstúpiť do svojej kritickej sekcie
2. Postup – Ak žiadny proces nie je vykonávaný vo svojej kritickej sekcii a je tu viac požiadaviek od procesov na vstup do ich kritickej sekcie, potom jednému z procesov bude povolené vstúpiť do kritickej sekcie. Výber procesu, ktorý dostane prístup, nesmie trvať nekonečne dlho.
3. Spravodlivosť - Žiadny proces nesmie nekonečne dlho brániť iným procesom vstúpiť do kritickej sekcie, t.j. každý proces musí mať rovnakú šancu vstúpiť do nej.
Predpokladáme, že každý proces sa vykonáva nenulovou rýchlosťou
Neexistuje žiadny predpoklad týkajúci sa relatívnej rýchlosti N procesov
6.7 ©2009Operačné systémy
Petersonovo riešenie
Dvojprocesorové riešenie (Two process solution) Predpokladajme, že inštrukcie LOAD a STORE sú atomické; t.j.,
nesmú byť prerušené. Atomická operácia je taká operácia, ktorá nemôže byť prerušená, musí sa vykonať len celá.
Dva procesy zdieľajú dve premenné: int turn; Boolean flag[2]
Premenná turn indikuje ktorý proces je na rade pre vstup do kritickej sekcie.
Prvky poľa sú inicializované na false. Pole indikátorov flag sa používa na indikovanie toho, ak proces je pripravený vstúpiť do kritickej sekcie. Ak flag[i] = true - proces Pi je pripravený vstúpiť do kritickej sekcie.
6.8 ©2009Operačné systémy
do {
flag[i] = TRUE;
turn = j;
while (flag[j] && turn == j);
critical section
flag[i] = FALSE;
remainder section
} while (TRUE);
Algoritmus pre proces Pi
6.9 ©2009Operačné systémy
Synchronizačný Hardware
Veľa systémov ponúka hardvérovú podporu pre kód kritickej sekcie. Jednoprocesory – mohli by zakázať prerušenia
Práve vykonávaný programový kód (bežiaci) bol by vykonávaný bez preempcie
Všeobecne, príliš neúčinné na multiprocesorových systémoch Operačné systémy používajúce toto nie sú široko
škálovateľné Moderné stroje ponúkajú špeciálne atomické hardwerové inštrukcie
Atomic = non-interruptable Buď testuj pamäťové slovo a nastav hodnotu Alebo vymeň obsahy dvoch pamäťových slov
6.10 ©2009Operačné systémy
Riešenie problému kritickej sekcie použitím zámku
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
6.11 ©2009Operačné systémy
TestAndSet Inštrukcia
Definition:
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
6.12 ©2009Operačné systémy
Riešenie použitím TestAndSet
Zdieľaná booleovská premenná lock., inicializovaná na hodnotu false. Riešenie:
do {
while ( TestAndSet (&lock ))
; // do nothing
// critical section
lock = FALSE;
// remainder section
} while (TRUE);
6.13 ©2009Operačné systémy
Swap Inštrukcia
Definícia:
void Swap (boolean *a, boolean *b)
{
boolean temp = *a;
*a = *b;
*b = temp:
}
6.14 ©2009Operačné systémy
Riešenie použitím Swap
Zdieľaná booleovská premenná lock inicializovaná na hodnotu FALSE; Každý proces má lokálnu booleovu premennú key
Riešenie:
do {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
// critical section
lock = FALSE;
// remainder section
} while (TRUE);
6.15 ©2009Operačné systémy
Ohraničené čakanie a vzájomné vylučovanie s TestandSet
do {
waiting[i] = TRUE;
key = TRUE;
while (waiting[i] && key)
key = TestAndSet(&lock);
waiting[i] = FALSE;
// critical section
j = (i + 1) % n;
while ((j != i) && !waiting[j])
j = (j + 1) % n;
if (j == i)
lock = FALSE;
else
waiting[j] = FALSE;
// remainder section
} while (TRUE);
6.16 ©2009Operačné systémy
Semafory
Synchronizačné prostriedky ktoré nevyžadujú aktívne, zamestnané čakanie (does not require busy waiting)
Semafor S – je celočíselná (integer) premenná Okrerm inicializácie je prístupná len cez dve štandardné operácie ktoré modifikujú
S: wait() a signal()
Pôvodne nazývané P() a V() Menej komplikované Môžu byť prístupné iba cez dve nedeliteľné (atomické) operácie
wait (S) {
while S <= 0
; // no-op
S--;
} signal (S) {
S++;
}
6.17 ©2009Operačné systémy
Semafor ako všeobecný synchronizačný prostriedok
Počítací (Counting) semafor – jeho integer hodnota môže mať neobmedzený rozsah
Binárny (Binary) semafor – integer hodnota môže mať rozsah iba medzi 0 a 1; môže byť jednoduchší z hľadiska implementácie
Semafor je tiež známy ako mutex locks
Je možné implementovať počítací semafor S ako binárny semafor
Poskytuje (reprezentuje) „mutual exclusion“ – vzájomné vylučovanie implementované na báze semaforov
Semaphore mutex; // initialized to 1
do {
wait (mutex);
// Critical Section
signal (mutex);
// remainder section
} while (TRUE);
6.18 ©2009Operačné systémy
Implementácia semaforu
Musí garantovať že žiadne dva procesy nemôžu vykonávať wait () a signal () na tom istom semafore v tom istom čase
Takto sa implementácia stáva problémom kritickej sekcie, kde wait a signal kód sú umiestnené v kritickej sekcii.
Mohol by mať teraz aktívne čakanie v implementácii kritickej sekcie
Avšak implementačný kód je krátky
Malé aktívne čakanie ak kritická sekcia je zriedkavo zamestnaná
Poznamenajme, že aplikácie môžu spotrebovať viac času v kritických sekciách a preto toto nie je dobré riešenie.
6.19 ©2009Operačné systémy
Implementácia semaforu bez aktívneho čakania
Ku každému semaforu je pričlenený front čakajúcich (procesov). Každý vstup vo fronte čakajúcich obsahuje dve dátové položky:
hodnota (typu integer)
ukazovateľ (pointer) na ďalší záznam v zozname
Dve operácie:
block (blokovať) – premiestni proces vyvolajúci operáciu do vhodného frontu čakajúcich.
wakeup (zobudiť) – premiestni jeden z procesov vo fronte čakajúcich do frontu pripravených (procesov).
6.20 ©2009Operačné systémy
Implementácia semaforu bez aktívneho čakania (Pokrač.)
Implementácia wait:
wait(semaphore *S) {
S->value--;
if (S->value < 0) {
add this process to S->list;
block();
}
} Implementácia signal:
signal(semaphore *S) {
S->value++;
if (S->value <= 0) {
remove a process P from S->list;
wakeup(P);
}
}
6.21 ©2009Operačné systémy
Uviaznutie a hladovanie
Deadlock (uviaznutie)– implementovanie semaforu s frontom čakajúcich môže vyústiť do situácie, kedy dva alebo viac procesov čakajú natrvalo na udalosť, ktorá môže byť spôsobená iba jedným z čakajúcich procesov. V prípade, že takýto stav nastane, hovoríme že procesy uviazli. Táto udalosť odpovedá vykonaniu operácie signal.
Uvažujme systém s dvoma procesmi P0 , P1 Oba procesy majú prístup k dvom semaforom S a Q nastaveným na hodnotu 1:
P0 P1
wait (S); wait (Q);
wait (Q); wait (S);
. .
signal (S); signal (Q);
signal (Q); signal (S);
Predpokladajme, že P0 ,P1 vykonajú po sebe wait(Q). Keď P0 vykoná wait(Q), musí čakať, až kým P1 vykoná signal(Q). Podobne, keď P1 vykoná wait(S) musí čakať, pokiaľ P0 vykoná signal(S). Preto operácie signal nemôžu byť vykonané, procesy P0 ,P1 sú uviaznuté.
6.22 ©2009Operačné systémy
Uviaznutie a hladovanie
Množina procesov sa nachádza v stave uviaznutia, ak každý proces v množine čaká na udalosť, ktorá môže byť spôsobená len nejakým procesom z danej množiny.
Udalosti, s ktorými sa predovšetkým stretávame a riešime ich, sú získanie a uvoľnenie zdrojov.
Starvation (hladovanie) – nekonečné blokovanie. Ide o stav, kedy proces čaká natrvalo (nekonečne) Proces nikdy nemôže byť odstránený zo semaforového radu, v ktorom je pozastavený.
Inverzia priority (Priority Inversion) - Problém plánovania, kedy proces nižšej priority drží zámok vyžadovaný procesom vyššej priority.
6.23 ©2009Operačné systémy
Klasické problémy synchronizácie
Problém ohraničeného zásobníka (Bounded-Buffer Problem)
Problém čitateľov a pisateľov (Readers and Writers Problem)
Problém obedujúcich filozofov (Dining-Philosophers Problem)
6.24 ©2009Operačné systémy
Problém ohraničeného zásobníka
N zásobníkov, každý je schopný držať jednu položku
Semafor mutex je inicializovaný na hodnotu 1
Semafor full je inicializovaný na hodnotu 0
Semafor empty je inicializovaný na hodnotu N.
6.25 ©2009Operačné systémy
Problém ohraničeného zásobníka (Pokrač.)
Štruktúra procesu „producent“
do {
// produce an item in nextp
wait (empty);
wait (mutex);
// add the item to the buffer
signal (mutex);
signal (full);
} while (TRUE);
6.26 ©2009Operačné systémy
Problém ohraničeného zásobníka (Pokrač.)
Štruktúra procesu „konzument“
do {
wait (full);
wait (mutex);
// remove an item from buffer to nextc
signal (mutex);
signal (empty);
// consume the item in nextc
} while (TRUE);
6.27 ©2009Operačné systémy
Problém čitatelia - pisatelia
Dátový objekt (typu súbor alebo záznam) je zdieľaný viacerými konkurenčnými procesmi
Čitatelia – iba čítajú z dátovej množiny, nevykonávajú akékoľvek „updates“ (procesy ktoré sa zaujímajú iba o čítanie)
Pisatelia – môžu aj čítať aj písať
Problém – dovoliť viacnásobným čítateľom čítať v tom istom čase. Len jeden môže mať prístup k zdieľaným dátam v tom istom čase.
Zdieľané dáta
Dátová množina (Data set)
Semafor mutex inicializovaný na hodnotu 1
Semafor wrt inicializovaný na hodnotu 1
Integer readcount inicializovaný na hodnotu 0
6.28 ©2009Operačné systémy
Problém čitatelia - pisatelia (Pokrač.) Štruktúra procesu „pisateľ“
do {
wait (wrt) ;
// writing is performed
signal (wrt) ;
} while (TRUE);
6.29 ©2009Operačné systémy
Štruktúra procesu Pisateľ - Čitateľ (Pokrač.)
Štruktúra procesu „čitateľ“
do { wait (mutex) ; readcount ++ ; if (readcount == 1)
wait (wrt) ; signal (mutex) // reading is performed
wait (mutex) ; readcount - - ; if (readcount == 0)
signal (wrt) ; signal (mutex) ; } while (TRUE);
6.30 ©2009Operačné systémy
Problém obedujúcich filozofov
Zdieľané dáta
Miska ryže (dátová množina) Semafor chopstick [5] inicializovaný na hodnote 1
6.31 ©2009Operačné systémy
Problém obedujúcich filozofov (Pokrač.)
Štruktúra filozofa i:
do {
wait ( chopstick[i] );
wait ( chopStick[ (i + 1) % 5] );
// eat
signal ( chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// think
} while (TRUE);
6.32 ©2009Operačné systémy
Problémy so semaformi
Nesprávne použitie semaforových operácií (výmena operácií, nahradenie operácií navzájom a pod.):
signal (mutex) …. wait (mutex)
wait (mutex) … wait (mutex)
Vynechať (opomenúť) wait (mutex) alebo signal (mutex) (alebo oba). V tomto prípade je porušené vzájomné vylúčenie alebo nastane uviaznutie.
6.33 ©2009Operačné systémy
Monitory
Abstrakcia vysokej úrovne, ktorá poskytuje vhodný a efektívny mechanizmus pre synchronizáciu procesov
Len jeden proces smie byť v danom čase aktívny vo vnútri monitora.
monitor monitor-name
{
// shared variable declarations
procedure P1 (…) { …. }
…
procedure Pn (…) {……}
Initialization code ( ….) { … }
…
}
}
6.34 ©2009Operačné systémy
Schematický pohľad na Monitor
6.35 ©2009Operačné systémy
Premenné typu Condition
condition x, y;
Programátor, ktorý potrebuje vytvoriť vlastnú (na mieru šitú) synchronizačnú schému, môže definovať jednu alebo viac premenných typu condition. Jediné operácie, ktoré môžu byť vyvolané na condition premenných sú wait a signal.
x.wait () – táto operácia znamená, že proces vyvolávajúci túto operáciu je suspendovaný, až kým iný proces vyvolá doleuvedenú operáciu x.signal ()
x.signal () – táto operácia obnoví presne jeden pozastavený proces- Ak žiadny proces nie je pozastavený, tak operácia signal nemá žiadny účinok, to znamená že stav x je ako keby operácia nebola nikdy vykonaná.
6.36 ©2009Operačné systémy
Monitor s premennými typu Condition
6.37 ©2009Operačné systémy
Riešenie k problému obedujúcich filozofov
monitor DP
{
enum { THINKING; HUNGRY, EATING) state [5] ;
condition self [5];
void pickup (int i) {
state[i] = HUNGRY;
test(i);
if (state[i] != EATING) self [i].wait;
}
void putdown (int i) {
state[i] = THINKING;
// test left and right neighbors
test((i + 4) % 5);
test((i + 1) % 5);
}
6.38 ©2009Operačné systémy
Riešenie k problému obedujúcich filozofov (Pokrač.)
void test (int i) {
if ( (state[(i + 4) % 5] != EATING) &&
(state[i] == HUNGRY) &&
(state[(i + 1) % 5] != EATING) ) {
state[i] = EATING ;
self[i].signal () ;
}
}
initialization_code() {
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
}
6.39 ©2009Operačné systémy
Riešenie k problému obedujúcich filozofov (pokrač.)
Každý filozof I invokuje operácie pickup()
a putdown() v nasledujúcej postupnosti:
DiningPhilosophters.pickup (i);
EAT
DiningPhilosophers.putdown (i);
6.40 ©2009Operačné systémy
Implementácia Monitoru použitím Semaforov
Premenné semaphore mutex; // (initially = 1)semaphore next; // (initially = 0)int next-count = 0;
Každá procedúra F bude nahradená
wait(mutex); …
body of F;
…if (next_count > 0)
signal(next)else
signal(mutex);
Vzájomné vylúčenie v rámci monitoru je zabezpečené.
6.41 ©2009Operačné systémy
Implementácia Monitoru
Pre každú premennú x typu condition máme:
semaphore x_sem; // (initially = 0)int x-count = 0;
Operácia x.wait môže byť implementovaná nasledovne:
x-count++;if (next_count > 0)
signal(next);else
signal(mutex);wait(x_sem);x-count--;
6.42 ©2009Operačné systémy
Implementácia Monitoru
Operácia x.signal môže byť implementovaná:
if (x-count > 0) {next_count++;signal(x_sem);wait(next);next_count--;
}
6.43 ©2009Operačné systémy
Monitor pre pridelenie jediného zdroja
monitor ResourceAllocator {
boolean busy; condition x; void acquire(int time) {
if (busy) x.wait(time);
busy = TRUE; } void release() {
busy = FALSE; x.signal();
} initialization code() {
busy = FALSE; }
}
6.44 ©2009Operačné systémy
Príklady Synchronizácie
Solaris
Windows XP
Linux
Pthreads
6.45 ©2009Operačné systémy
Synchronizácia Solaris-u
Implementuje rozmanité zámky pre podporu multitasking-u, multithreading-u (zahrňajúc vlákna reálneho času), a multiprocessing
Používa adaptive mutexes kvôli účinnosti pri ochrane dát pre kratšie segmenty kódu
Používa premenné typu condition a čitateľ-pisateľ zámky ktoré sú relatívne náročné na implementáciu, preto sa používajú iba na dlhšie segmenty kódu (ktoré potrebujú prístup k dátam)
Používa turnikety Turniket je frontová štruktúra obsahujúca vlákna blokované na zámku. Solaris 2 používa turnikety na poradie frontu vlákien čakajúcich na získanie buď adaptívneho mutexu alebo čitateľ-pisateľ zámku.