Cuprins capitolul 1– Istoria sistemelor de operare 2


Substituirea variabilelor în subprogram



Yüklə 359,7 Kb.
səhifə5/6
tarix03.11.2017
ölçüsü359,7 Kb.
#29140
1   2   3   4   5   6

6.10 Substituirea variabilelor în subprogram

Se detaliază felul în care variabilele se substituie una pe cealalta în cadrul execuţiei unei subrutine sau unui subprogram. Presupunem că o anume subrutină numită “demo” depinde de 3 variabile a,b,c; primlinie a subrutinei va fi :



subroutine demo(a,b,c)

Se presupune că apelarea în programul principal are loc astfel:



call demo(x,y,z)

unde x,y,x sunt varibile ale programului principal.

Tipul şi dimensiunile acestor variabile sunt declarate în programul principal ,iar acestea trebuie să corespunda tipului şi dimensiunilor lui a,b,c declarate în subrutina.Valorile lui x,y,z vor fi stocate de Fortran în anumite zone de memorie desemnate ca în diagrama de mai jos:



x → Δ

y → Δ

z → Δ

Când subrutina “demo” este apelată, Fortran atribuie variabilelor aceleaşi locaţii de memorie variabilelor a,b ,c precum în schema de mai jos:



x → Δ ← a

y → Δ ← b

z → Δ ← c

Pe măsură ce subrutina “demo” rulează, variabilele a,b,s pot să îşi schimbe valorile cu unele noi. Dar,din moment ce x,y,z împart aceeaşi zonă de memorie cu a,b,c şi acestea, din urma, îşi vor schimba valorile. Ca’ând subrutina se va încheia şi se va întoarce în programul principal,a,b,c nu mai sunt variabile active,dar x,y,z reţin valorile finale ale lui a,b,c din finalul subrutinei.

Există o modalitate de a păcăli Fortran pentru a nu mai schimba aceste valori. Se presupune că apelarea subrutinei se face astfel:



call demo(x,(y),z)

Când variabila este închisă între paranteze ,Fortran consideră (y) ca fiind o nouă expresie şi îi atribuie o zonă de memorie diferită de locaţia lui y,dar cu aceeaşi valoare a lui y.Ultima diagramă se schimbă astfel:



x → Δ ← a

y → Δ

(y) → Δ ← b

z → Δ ← c

Acum, din moment ce b îşi schimbă valoarea de-a lungul execuţiei subrutinei ,y rămâne neafectat,astfel încât la finalul subrutinei ,acesta va avea valoarea iniţială.

Analiza de mai sus se aplică atât subprogramelor, cât şi subrutinelor. Schimbările în funcţionarea variabilelor, în timpul execuţiei funcţiei unui subprogram induce schimbări corespunzătoare în variabilele utilizate pentru apelarea funcţiei subprogramului.

7 Ce reprezinta RPC ?

7.1 Ce este RPC?

RPC(Remote Procedure Calls) este o tehnică puternică pentru construirea distribuită , bazată pe aplicaţii de tip client-server. Ea se bazează pe extinderea noţiunii de convenţional, sau apelarea procedurii locale, astfel încât procedura numită nu trebuie să existe în spaţiul aceleiaşi adrese ca şi procedura de apel.

Cele două procese pot fi în acelaşi sistem, sau pot fi pe diferite sisteme cu o reţea conectându-le. Prin utilizarea RPC, programatorii de aplicaţii distribuite evita detaliile interfaţei cu reţeaua. Independenţa transportului RPC izoleaza aplicaţiile de la elementele fizice şi logice ale mecanismului de comunicaţii de date şi permite aplicarea de a folosi o varietate de transporturi.

7.2Cum funcţionează RPC ?

RPC este similar cu un apel de funcţie. Ca un apel de funcţie, atunci când RPC-ul este realizat, argumentele de aşteptare sunt transmise de procedură la distanţă, iar apelantul aşteaptă un răspuns să fie returnate de procedură la distanţă. Fig.1 de mai jos prezinta fluxul de activitate care are loc în timpul unui apel RPC între două sisteme în reţea.

Clientul face un apel de procedură, care trimite o cerere la server si aşteaptă . Firul este blocat în urma prelucrării până cand un răspuns este primit, sau este in afara reţelei.

În cazul în care cererea ajunge, serverul solicită o expediere de rutină care efectuează serviciul solicitat, şi trimite răspunsul inapoi la client. După ce apelul RPC este finalizat, programul client continuă. RPC sprijină în mod specific aplicaţiile de reţea.





Fig. 1 Mecanismul Remote Procedure Calling

O procedură la distanţă este identificata în mod unic de tripletul: (numărul programului, numărul de versiune, numărul de procedură). Numărul programului identifică un grup de proceduri legate de distanţă, fiecare dintre acestea are un număr unic de procedură. Un program poate cuprinde una sau mai multe versiuni. Fiecare versiune constă într-o colecţie de proceduri care sunt disponibile pentru a fi numite la distanţă. Numerele de versiune permit mai multe versiuni ale unui protocol RPC să fie disponibile simultan. Fiecare versiune conţine numărul de aa procedurilor care pot fi apelate de la distanţă. Fiecare procedură are un numar de procedură.

7.3 Privire de ansamblu la rutinele de interfaţă

RPC are niveluri multiple la interfaţa de aplicaţie pentru serviciile sale. Aceste niveluri oferă grade diferite de control echilibrat cu diferite sume de cod de interfaţă pentru a fi puse în aplicare. În scopul de a controla creşterea şi complexitatea. Această secţiune oferă un rezumat al rutinelor disponibile la fiecare nivel.



Interfeţele simplificate sunt folosite pentru a face apeluri de procedura la distanţa la rutinele pe alte maşini, şi să specifice doar tipul de transport ce trebuie să folosească. Rutinele de la acest nivel sunt utilizate pentru majoritatea aplicaţiilor.

Nivelul funcţiei de rutină simplificat

rpc_reg () - Registrele ca un program de RPC cu privire la toate transporturile de tipul specificat.

rpc_call () - Solicită procedura specificată pe gazda de la distanţă specificată.

rpc_broadcast () - Emite un mesaj de apel pentru toate transporturile de tipul specificat. Interfeţele standard sunt împărţite în: cel mai înalt nivel, nivel intermediar, nivel de experţi, cât şi la nivel de jos. Aceste interfeţe dau un control dezvoltator mult mai mare asupra parametrilor de comunicare, cum ar fi transportul fiind folosit cât de mult timp să aştepte înainte de a răspunde la erori şi retransmiterea cererii, şi aşa mai departe.

  1. Proceduri de nivel intermediar

Interfaţa de nivel intermediar RPC permite să fie controlate detaliile. Programele scrise la aceste niveluri mai mici sunt mult mai complicate, dar pot rula mai eficient. Nivelul intermediar permite specificarea tipului de transport utilizat.

clnt_tp_create () - Creează un client mâner pentru transportul specificat.

clnt_tp_create_timed () - Similar cu "clnt_tp_create ()", dar permite programatorului sa specifice termenul maxim permis.

svc_tp_create () - Creează un server mâner pentru transport specificat.

clnt_call () - Clientul solicită o procedură de a trimite o cerere la server.

  1. Proceduri de nivel de experţi

Nivelul de experţi conţine un set de rutine mai mare cu care să se precizeze parametrii legati de transport. Utilizarea acestor rutine este următoarea:

clnt_tli_create () - Creează un client mâner pentru transport specificat.

svc_tli_create () - Creează un server mâner pentru transport specificat.

rpcb_set () - Solicită rpcbind ptr. a se stabili o hartă între un serviciu RPC şi o adresă de reţea.

rpcb_unset () - Şterge o cartografiere stabilita de rpcb_set ().

rpcb_getaddr () - Solicită rpcbind pentru a obţine adresele de servicii de transport specificate RPC.

svc_reg () - Asociaza programul specificat şi versiunea cu numărul pereche de expediere specificat de rutină.

svc_unreg () - Şterge o asociaţie stabilita de svc_reg ().

clnt_call () - Clientul solicită o procedură de a trimite o cerere la server.

  1. Proceduri de nivel inferior

Nivelul de jos conţine rutine utilizate pentru controlul complet de opţiuni de transport.

clnt_dg_create () - Creează un client RPC, mâner pentru programul specificat la distanţă, folosind o conexiune de transport.

svc_dg_create () - Creează un server RPC mâner, folosind o conexiune de transport.

clnt_vc_create () - Creează un client RPC, mâner pentru programul specificat la distanţă, folosind un transport orientat pe conexiune.

svc_vc_create () - Creează un server RPC mâner, folosind un transport orientat pe conexiune.

clnt_call () - clientul solicită o procedură de a trimite o cerere la server.

8. COMUNICARE ÎNTRE PROCESE - SINCRONIZARE, INTERBLOCAJE

8.1 CE ESTE UN PROCES ?

Entitatea dinamică reprezintă unitatea de lucru a unui sistem de calcul, conţine un program, are nevoie de o serie de resurse, menţine date care formează starea procesului şi care execută, în mod secvenţial, instrucţiunile programului asociat.

Procesul independent este un proces care nu este afectat de executarea altor procese şi care nu afectează modul de funcţionare a altor procese.

Procesul cooperant este procesul care influenţează sau este influenţat de alte procese care rulează pe acelaşi sistem sau pe alte sisteme.

Comunicare indirectă:

• Prin intermediul unui mailbox

• Fiecare mailbox are un ID unic

• Mesajele sunt trimise şi preluate direct din mailbox

• Se pot conecta multe procese la un mailbox

• O pereche de procese poate comunica prin mai multe legături



Comunicare directă:

• Conectare directă între procese.

• Legătura poate fi unidirecţională sau bidirecţională.

• Nu se folosesc variabile partajate.

Se folosesc nume explicite: send(P,msg); receive(Q,msg)

Operaţii: send(msg); receive(msg)



Comunicare prin partajare de memorie:

• Procese şi fire

• Problema secţiunii critice

• Operaţii atomice



Comunicare prin transfer de mesaje:

a) Pipe/fişiere

b) Semnale

c) Direct, fără buffer

d)Cu buffer – Mailbox, Sockets

• Adresa – Domain+Port

• Tip – Stream, Datagrams

• Api – Socket, Bind, Connect, Read/Write



8.2Comunicarea prin partajarea memoriei

O zonă de memorie este alocată şi stabilita ca zonă de memorie comună. Procesele ataşează zona comună propriului spaţiu de adrese. Sistemele de operare mapează zona de memorie în spaţiul de adrese al ambelor procese. Cele două procese care comunică, citesc şi scriu în zona de memorie comună.



Procesele care comunică au acces la aceeaşi zonă din memoria fizică.



Avantaje:

• Kernelul intervine doar la stabilirea memoriei comune şi la închiderea acesteia

• Viteza mare de comunicare

• Cantitate mare de date partajate

• Nu se copiază datele de mai multe ori

• Kernelul nu intervine în comunicare

• Dacă utilizăm fire, acestea partajează toate datele globale din program (cel mai simplu caz)

Dezavantaje:

• E nevoie de mecanisme de sincronizare

• Nu trebuie să scrie ambele procese în acelaşi timp

• Operaţiile de scriere în zona de memorie comună conţin secţiuni critice în proces

• operaţiile de scriere trebuiesc realizate în mod atomic.

• Nu se poate implementa pentru procese care rulează pe maşini diferite (decât cu costuri de eficienţă prea mari)



8.3 Comunicarea prin transfer de mesaje

Transferul de mesaje (message passing) utilizează apelurile de sistem send şi receive:



send(destination, &message); - trimite un mesaj la destinaţia dată (un proces)

receive(source, &message); - primeşte un mesaj de la sursa specificată (un proces);

Dacă nu este disponibil nici un mesaj, destinatarul este blocat până la sosirea mesajului.

Realizează o comunicare directă între două procese. Fiecare proces trebuie să cunoască numele celuilalt proces pentru a putea comunica.

Avantaje:

• Uşor de implementat (pentru mesaje de mărime fixă), kernelul intervine în comunicare

• Procesele se pot sinroniza uşor folosind operaţii blocante

• Se poate implementa pentru procese care rulează pe maşini diferite

• Operaţiile de scriere nu trebuiesc realizate în mod atomic.

Dezavantaje:

• Kernelul intervine în comunicare, viteza redusă

• Datele se copiază de mai multe ori

• Ineficient în cazul blocurilor mari de date



MONITOARE

Monitorul este o primitivă de sincronizare de nivel înalt (introdusă de Hoare (1974) şi Brinch Hansen (1975)), constând într-un pachet special de proceduri şi structuri de date, cu proprietatea că procesele pot apela procedurile unui monitor, dar nu pot accesa direct structurile sale de date sau într-un monitor, doar un proces poate fi activ la un moment dat (dacă între timp alt proces încearcă, el este blocat automat până monitorul e liber).

Monitoarele sunt concepte ale limbajelor de programare, tratate de compilator - de exemplu compilatorul văzând că o procedură este definită într-un monitor, tratează apelurile ei altfel. Este sarcina compilatorului, nu a programatorului, să implementeze excluderea mutuală asupra procedurilor din monitor (compilatorul adaugă automat codul necesar - de exemplu foloseşte un semafor binar sau un mutex).

Deşi monitoarele ne oferă excluderea mutuală, ele trebuie îmbogăţite şi cu un instrument de sincronizare a proceselor - să putem bloca procesul apelant în aşteptarea unor semnalizări din partea altor procese privind anumite evenimente.


BARIERE

Barierele sunt un mecanism de sincronizare folosit atunci când mai multe procese execută activităţi împărţite în etape şi nici un proces nu are voie să treacă la o etapă nouă până când toate celelalte procese nu sunt şi ele gata să treacă la etapa respectivă.

În acest scop, între etape sunt plasate bariere - practic, apeluri ale unei primitive ”barrier” (implementată în general prin intermediul unei funcţii de bibliotecă), care blochează procesul apelant până ce şi celelalte procese ajung în punctul respectiv - din acel moment vor reporni toate.

8.4 COMUNICARE ÎN SISTEME CLIENT – SERVER

Socket = punct de comunicare (capăt al unei linii de comunicare)

Comunicarea dintre două procese va folosi o pereche de sockeţi, unul pentru server şi unul pentru client.





Instrumente de comunicare între procese:

Regiuni critice
Regiune critică (critical region) sau secţiune critica (critical section) reprezintă o parte din program care accesează o resursă partajată (structură de date sau dispozitiv).

Excluderea mutuală (mutual exclusion) implică împiedicarea folosirii simultane de către mai multe procese a unei resurse partajate.

Dacă am putea face ca oricare două procese ce partajază anumite resurse să nu fie niciodată în acelaşi timp în regiunile lor critice, am putea evita cursele. Deşi această cerinţă evită condiţiile de cursă, ea nu este suficientă pentru ca procesele paralele să coopereze corect şi eficient folosind datele partajate.


Pentru a avea o soluţie buna, trebuie îndeplinite următoarele patru condiţii:

1. Oricare două procese nu se pot afla simultan în regiunile lor critice.

2. Nici un fel de presupunere nu se poate face asupra vitezelor sau numărului de procesoare.

3. Nici un proces care rulează în afara regiunii sale critice nu poate bloca alt proces să intre în regiunea sa critică.

4. Nici un proces nu trebuie să astepte la infinit pentru a intra în regiunea sa critică.
Dezactivarea întreruperilor
Metoda: procesul dezactivează întreruperile imediat ce a intrat în regiunea critică şi le reactivează imediat înainte de a ieşi din ea.

Astfel, pe parcursul regiunii critice procesul nu mai poate fi întrerupt de nucleu, pentru a comuta procesorul la alt proces (comutarea între procese este rezultatul întreruperilor de ceas sau de alt tip, iar acestea sunt dezactivate) -deci nici un alt proces nu îl mai poate incomoda.


Avantaje/dezavantaje:

  • nu este bine să dai proceselor utilizator puterea de a dezactiva întreruperile; dacă nu le mai reactiveaza ?

  • dacă sistemul are mai multe procesoare, dezactivarea întreruperilor afectează doar procesorul care a executat instrucţiunea de dezactivare;

  • celelalte procesoare vor rula în continuare procese, care ar putea accesa resursele partajate;

  • pentru nucleul SO este convenabil să dezactiveze întreruperile cât timp execută câteva instrucţiuni de actualizare a unor variabile sau liste;

  • dacă de exemplu, ar apărea o întrerupere cât timp lista proceselor gata de execuţie este într-o stare inconsistentă, ar putea apărea condiţii de cursă.

Variabile zăvor

Metoda: se foloseşte o variabilă partajată (zăvor) având valoarea iniţială 0; când un proces vrea să intre în regiunea critică, verificaă zăvorul; dacă este 0, îl face 1, intra în regiunea critică, iar la sfârsit îl face 0; dacă este deja 1, aşteaptă să devină 0.

Deci zăvor = 0, înseamnaă că nici un proces nu este în regiunea critică şi zăvor =1 înseamnaă că exista un proces aflat în regiunea criticaă.


Alternarea strictă
Metoda: se foloseşte o variabilă partajată care reţine al cui este rândul, iar fiecare proces înaintea regiunii critice aşteapta să aibe valoarea potrivitaă, intră în regiunea critică, iar la ieşire îi schimbă valoarea pentru a-i da voie procesului celălalt.

Astfel, metoda nu este utilă când unul dintre procese este mult mai lent decât celălalt.

De asemenea, metoda impune proceselor să alterneze strict efectuarea regiunilor critice; aceasta poate cauza limitări - de exemplu, în exemplul anterior cu printarea fişierelor, alternarea strictă ar împiedica un proces să înregistreze consecutiv două fişiere la printare.

Verificarea în continuu a unei variabile până când are o anumită valoare se numeşte aşteptare ocupată (busy waiting); ea trebuie în general evitată, deoarece iroseşte timp pe procesor; este utilă doar când probabilitatea ca aşteptarea să fie scurtă este rezonabilă.

Un zăvor care foloşeste aşteptarea ocupată se numeşte spin lock.

Solutia lui Peterson
Metode de obţinere a excluderii mutuale fără alternare strictă au obţinut T.Dekker (matematician olandez), apoi (mai simplu) G.L.Peterson (în 1981).

Algoritmul lui Peterson este format din două proceduri ce trebuie executate în fiecare proces la intrarea, respectiv ieşirea din regiunea critică şi este ilustrat mai jos (fiecare proces apelează procedurile cu numărul sau de ordine, 0 sau 1):


#define FALSE 0

#define TRUE 1

int turn;

int interested[2]={FALSE,FALSE};

void enter_region(int process){

int other;

other=1-process;

interested[process]=TRUE; turn=process; while(turn==process && interested[other]==TRUE);

}

void leave_region(int process)

{

interested[process]=FALSE;

}

  1. Instrucţiunea TSL (Test and Set Lock)

TSL REGISTER, LOCK citeşte conţinutul locaţiei de memorie LOCK în registrul REGISTER şi stochează valoarea 1 la adresa LOCK – instrucţiunea este implementată hardware pt. a fi indivizibilă.



enter_region:

TSL REGISTER, LOCK | copy lock to register and set lock to 1

CMP REGISTER, #0 | was lock 0?

JNE enter_region | if it was non zero, lock was set by

| another process, so loop

RET | return to caller, critical region entered



leave_region:

MOVE LOCK, #0 | store a 0 in lock

RET | return to caller, critical region left


  1. Primitivele Sleep si Wakeup

Soluţia lui Peterson şi instrucţiunea TSL garantează excluderea mutuală. Astfel, aşteptarea activă prezinta urmatoarele inconveniente: consumă degeaba timpi processor, respective poate avea efecte nedorite (de exemplu, in cazul proceselor cu priorităţi diferite).

Primitivele sleep şi wakeup elimină posibila aşteptare activă înainte de intrarea într-o SC:



  1. sleep – apel de sistem care are ca efect blocarea procesului appellant

  2. wakeup – apel de sistem care acceptă, ca parametru, procesul ce trebuie deblocat



  1. SEMAFOARE

Semafor (1965, Dijkstra) – o variabilă întreagă ce indică numărul de semnale de deblocare salvate.

Operaţii:

  • down - decrementează un semafor doar dacă valoarea lui este strict mai mare decât 0

dacă semaforul are valoarea 0, atunci procesul se blochează (intră în sleep)

  • up - incrementează valoarea unui semafor dacă unul sau mai multe procese sunt blocate pe respectivul semafor (nu au putut continua o operaţie down anterioară pe semafor cu valoarea 0), se va debloca unul dintre ele, pentru a-şi încheia operaţia down operaţia up nu poate bloca un process.

  1. MUTEX

Un mutex este o variabilă cu două stări posibile: deschis/închis şi în legatură cu care sunt definite două operaţii (proceduri):

a) ”mutex lock”: dacă mutex-ul este deschis, el se închide, iar apelantul continuă (nu se blochează); dacă mutex-ul este închis, apelantul este blocat (la mutex-ul respectiv);

b) ”mutex unlock”: dacă mutex-ul este deschis, nu face nimic; dacă mutex-ul este închis, îl deschide, apoi alege aleator pe unul din cei care erau blocaţi la el (dacă există) şi îl trezeşte - acesta finalizează închiderea, a.î. în final mutex-ul rămâne tot închis; dacă nu era nimeni blocat la mutex, acesta rămâne deschis; în ambele cazuri, cel care a apelat ”mutex unlock” continuă (nu se blochează).
Mutex-urile sunt versiuni simplificate de semafoare, pe care le folosim atunci când nu vrem sa număram ci doar să obţinem excluderea mutuală; stările deschis / închis semnifică permisiunea / interzicerea de a intra în regiunea critică; înainte de a intra în regiunea critică se execută ”mutex lock” asupra unui mutex, iar dupa ieşirea din regiunea critică se execută ”mutex unlok” asupra acestuia.

Mutex-urile sunt uşor şi eficient de implementat şi de aceea sunt folosite mai ales la excluderea mutuală a thread-urilor implementate în spaţiul utilizator.



Yüklə 359,7 Kb.

Dostları ilə paylaş:
1   2   3   4   5   6




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin