SOMIPPRaspunsuri
SOMIPPRaspunsuri
SOMIPPRaspunsuri
secveniale,
cu multiprogramare,
cu prelucrare multipl,
Sistemele de timp real funcioneaz, de obicei, n cadrul unor sisteme de comand i este necesar ca
valorile anumitor atribute s se ncadreze n limite destul de restrictive, dictate de dinamica proceselor
comandate.
nregistrare. Rezultatele msurrilor sunt periodic nregistrate; valorile lor sunt afiate pe un tablou
de bord i recopiate ntr-un fiier ("jurnal de bord") n scopul unor prelucrri ulterioare (date
statistice).
Securitate. n cazul n care unul dintre parametrii msurai depete o valoare critic predefinit
reactorul trebuie oprit imediat.
7. Sisteme tranzacionale
Caracteristicile principale:
sistemul gestioneaz un set de informaii sau baze de date, care pot atinge volume importante de
informaie;
asupra acestor informaii pot fi executate un anumit numr de operaii predefinite sau tranzacii,
adesea interactive;
sistemul este dotat cu un mare numr de puncte de acces i un mare numr de tranzacii se pot
derula simultan. Caracteristicile obligatorii ale unui astfel de sistem tranzacional sunt
disponibilitatea i fiabilitatea; pentru unele sisteme poate fi important i tolerana la defeciuni. O
caracteristic important ale sistemelor tranzacionale este multitudinea activitilor paralele, iar n
multe cazuri i repartizarea geografic a componentelor.
Problemele care apar datorit conceptului de partajare a timpului sunt o combinaie a problemelor existente
n cazul unui calculator individual cu cele din sistemele tranzacionale. Caracteristicile obligatorii ale unui
astfel de sistem mbin, n egal msur, calitile unui sistem de operare al unui calculator individual i al
unui sistem tranzacional, cum ar fi: disponibilitatea, fiabilitatea, securitatea, exploatarea optim a
caracteristicilor resurselor fizice, calitatea interfeei i serviciilor utilizatorului, facilitatea adaptrii i
extensibilitii.
9. SO i procesele
Noiunea de proces este asociat conceptului de lucrare i poate fi definit ca o suit temporal de execuii
de instruciuni, considerat ca fiind o entitate de baz n descrierea sau analiza funcionrii unui sistem.
Evoluia n timp a unui proces presupune un consum de resurse, dictat de natura i complexitatea
instruciunilor de execuie. n particular, rezult c ori de cte ori se execut procedurile de sistem,
resursele, pe care le utilizeaz acesta, intr n administrarea procesului, care a cerut serviciul. Resursele
alocate unui proces variaz n timp.
10. Maina extins i maiina ierarhic
Setul de instruciuni realizat hardware mpreun cu instruciunile suplimentare ale sistemului de operare
formeaz sistemul de comenzi al mainii extinse.
Nucleul sistemului de operare va fi executat pe maina goal, iar programele utilizatorului pe maina
extins.
11. Alte puncte de vedere asupra SO: abordarea funcional, interfaa cu utilizatorul
Sistemele de operare pot fi abordate din diferite puncte de vedere, cum ar fi SO i procesele, SO i maina
extins sau SO i maina ierarhic. Exist i alte puncte de vedere asupra sistemelor de operare pe care un
specialist ar trebui s le cunoasc.
Abordare funcional-Pentru un utilizator obinuit, convins c un calculator este doar un instrument care l
ajut n soluionarea unor probleme din domeniul su de activitate, noiunile, cum ar fi administrarea
memoriei cu paginaie sau driverele dispozitivelor, nu semnific prea multe. Destinaia principal a unui
sistem de operare pentru aceast categorie de utilizatori este punerea la dispoziie a unui set de programe
care l-ar ajuta n formularea i soluionare problemelor concrete ce in de domeniul su de activitate.
Abordare din punctul de vedere al interfeei cu utilizatorul
Interfaa sistemului de operare cu utilizatorul prezint un interes aparte. Progresul n acest domeniu este
spectaculos, dac vom lua n consideraie c n primele sisteme de operare utilizatorul era obligat s indice
n mod explicit i manual (n regim textual) fiecare pas, orict de nesemnificativ ar fi prut. Formularea
pailor cu ajutorul unui limbaj specializat, cum ar fi Job Control Language (JCL), nu a schimbat substanial
situaia.
12. Evoluia SO: de la "poart deschis " la tratarea pe loturi
Primele sisteme erau caracterizate prin prelucrarea secvenial a taskurilor. Timpul de execuie a
programelor era relativ mare, instrumentele de depanare primitive, fiecare programator i ncrca n mod
individual programul (pachetul de cartele perforate), apsa butoane, controla coninutul locaiunilor de
memorie, etc. (1950 1956). Au fost propuse programe de monitorizare (monitoare), care treceau de la o
lucrare la alta n mod automat, utilizatorul fiind responsabil de organizarea corect a programelor n cadrul
unui pachet primele ncercri de prelucrare pe loturi (1956 1959).
Dup 1965 au aprut primele sisteme cu partajare a timpului (time sharing), au fost propuse sisteme
sofisticate de administrare a informaiei Memoria virtual i mainile virtuale sunt nite principii care
nici pn astzi nu au fost exploatate pn la capt. Progresele ultimilor ani n domeniul resurselor tehnice
au permis implementarea acestor principii nu numai n cadrul sistemelor de calcul mari, ci i pentru
calculatoarele personale.
Primele calculatoare nu dispuneau de sisteme de operare. Fiecrui utilizator i se rezerva pentru un timp
determinat calculatorul cu toate resursele acestuia. Interaciunea era direct, programul i datele fiind
introduse n mod manual sub form de zerouri i uniti. Utilitele care au aprut aveau destinaia de a asista
elaborarea programelor (asambloare, compilatoare, etc.) sau de a facilitata operaiile de intrare-ieire.Acest
mod de exploatare, numit "poart deschis" , era de o eficacitate minim. Din aceast cauz la sfritul
anilor '50 au aprut primele "monitoare de nlnuire" - programe care permiteau executarea secvenial a
unui set de lucrri, pregtite anticipat, trecerea de la o lucrare la alta fiind automatizat.
13. Evoluia SO: multiprogramarea i partajarea timpului
Utilizarea principiului multiprogramrii sau partajarea memoriei ntre mai muli utilizatori a permis o
utilizare i mai bun a procesorului central. Exploatarea unui calculator conform principiului timpului
partajat ofer utilizatorilor posibiliti analogice unui calculator individual, permind beneficiul unor
servicii comune la un pre redus.
14. Organizarea intrrilor - ieirilor n memorii tampon
Pentru excluderea influenei perifericelor asupra vitezei de lucru a sistemului de calcul s-a propus s se
pstreze n memorie n anumite zone tampon datele de intrare i rezultatele mai multor lucrri.Dei
utilizarea memoriilor tampon prezint o serie de avantaje, totui dou momente negative pot fi menionate:
atunci cnd lucrarea n curs de execuie are nevoie de nite date unitatea central rmne inactiv pe
toat perioada citirii acestora;
o lucrare de scurt durat, sosit n timpul execuiei unei lucrri "lungi", trebuie s atepte
terminarea acesteia din urm.
15. Multiprogramarea
Multiprogramarea este un termen utilizat n cazul unui sistem n care pot exista simultan cteva procese
n stare de execuie. Un proces se consider n stare de execuie, dac calculele au nceput, dar la momentul
considerat nu au fost terminate sau ntrerupte. Multiprogramarea permite meninerea unitii centrale
n stare activ pentru perioada ncrcrii programelor sau operaiilor de intrare-ieire. Acest mod de
funcionare este adaptat tratrii pe loturi pe un calculator, care nu dispune de un mecanism de
reamplasare dinamic.
16. Sisteme cu timp partajat
Destinaia principal a unor astfel de sisteme este furnizarea serviciilor necesare unei mulimi de utilizatori,
fiecare dintre ei beneficiind de servicii:
Problemele care apar datorit conceptului de partajare a timpului sunt o combinaie a problemelor existente
n cazul unui calculator individual cu cele din sistemele tranzacionale i pot fi clasificate dup cum
urmeaz:
Mai menionm standardul de-facto SPARC Complience Definition, propus de organizaia SPARC
International,
Pentru lumea UNIX este foarte important i standardul limbajului de programare C, adoptat mai nti de
ANSI i apoi de ISO. n acest standard sunt specificate, n afara limbajului C, bibliotecile necesare ntr-o
realizare standard. Deoarece chiar de la apariie limbajul C i sistemele de programare respective erau
strns legate de UNIX, componentele bibliotecilor standard corespundeau exact mediului standard al SO
UNIX.
21. Sisteme de operare cu micronucleu
Micronucleul este partea minim principal a unui sistem de operare, folosit pentru asigurarea
modularitii i transportabilitii.
Noiunea de micronucleu a fost introdus de compania Next prin sistemul de operare cu micronucleul
Mach.
Urmtorul SO cu micronucleu a fost MS Windows NT, n care momentul principal declarat era, n afara
modularitii, transportabilitatea. Acest sistem de operare poate fi utilizat n sistemele mono- i
miltiprocesor, bazate pe procesoarele Intel, Mips, i Alpha
Au aderat la tehnologia micronuclear i companiile Novell/USL, Open Software Foundation (OSF),
IBM, Apple i altele. Unul din concurenii principali ai lui NT n domeniul SO cu micronucleu sunt Mach
3.0, creat n Universitatea Carnegy-Mellon, i Chorus 3.0 al companiei Chorus Systems.
22. Modul secvenial de execuie a unui program. Noiuni fundamentale
Un program secvenial = o mulime de proceduri, care se pot apela reciproc. Fiecrei proceduri i este
asociat un segment distinct de procedur. Datele sunt reprezentate prin segmente, pot fi proprii unei
proceduri sau partajate ntre mai multe proceduri.
Numim activitate fenomenul care rezult din execuia nentrerupt a unei proceduri unice. !!Execuia unui
program secvenial const dintr-un lan de activiti!!!!
Numim context al unei activiti mulimea informaiilor accesibile procesorului n cursul acestei activiti.
Contextul activitii este compus din contextul procesorului (registrele programabile i interne) i contextul
memoriei (segmentul procedurii i segmentul datelor). Trecerea de la o activitate la alta este realizat de
instruciuni speciale: apelarea i returul din procedur, care realizeaz comutarea contextului.
23. Modul secvenial de execuie a unui program. Apelarea i returul
Operaiile executate la apelarea i returul procedurii sunt urmtoarele:
Apelare
1. alocarea unei zone n stiva de execuie pentru mediul procedurii apelate (dimensiunea acestei zone,
cu excepia spaiului de lucru, este cunoscut anticipat)
temp:=baza
baza:=top
top:=top+dimensiunea mediului
2. salvarea informaiilor de retur
baza_veche:=temp
memorizarea adresei de retur
3. ordonarea parametrilor
4. executarea unei ramificaii la procedura apelat.
Retur
1. salvarea rezultatului ntr-un amplasament stabilit
2. restabilirea informaiilor de retur i eliberarea mediului
temp:=adresa de retur
top:=baza
baza:=baza_veche
3. returul
ramificare *temp ramificare indirect
24. Activiti asincrone i protecia reciproc ntre activiti
Pentru cazuri mai generale sunt necesare mecanisme suplimentare, cum ar fi conceptele de asincronism sau
de protecie reciproc ntre activiti.
Prin asincronism nelegem efectul care l pot avea asupra derulrii unei activiti anumite evenimente
exterioare.
Numim protecie reciproc ntre activiti o modificare mai profund a contextului, atunci cnd se
trece de la o activitate la alta, n comparaie cu ceea ce are loc n cazul unei simple apelri de
procedur.
Un caz tipic de asincronism este executarea intrrilor-ieirilor simultan cu execuia unui program. Trebuie
s fie asigurat posibilitatea informrii programului despre terminarea unui transfer de informaii.
25. Mecanisme de comutare a contextului
Comutarea contextului unui procesor permite executarea ntr-o manier indivizibil (atomar) a
urmtoarelor dou operaii:
trecerea cuvntului de stare ntr-un amplasament specificat al memoriei,
ncrcarea n cuvntul de stare a coninutului unui alt amplasament specificat al memoriei. Comutarea
contextului poate fi necesar din mai multe cauze distincte. Presupunem c fiecrei cauze i-a fost asociat un
numr de ordine. Pot fi ntlnite dou scheme de comutare a contextului.
1. Salvare n amplasamente fixe.
2. Salvare ntr-o stiv.
26. ntreruperi
O ntrerupere este comutarea contextului procesorului declanat de o cauz extern derulrii instruciunii
curente. Fizic, ntreruperea nseamn trimiterea unui semnal procesorului, acest semnal provocnd
schimbarea strii unuia dintre indicatorii, consultai n cursul executrii fiecrei instruciuni. Semnalul
poate proveni de la alt procesor, de la un organ de I/E, de la un dispozitiv extern, i n genere, de la orice
proces fizic, extern procesorului ntrerupt. O ntrerupere permite s cerem procesorului s suspende
executarea programului curent, din primul punct ntreruptibil, i s treac la execuia unui program
predefinit. Acesta din urm este numit program de tratare a ntreruperii (interrupt handler, eng., traitant
de l'interruption, fr.). Programul de tratare a ntreruperii este executat ntr-un context diferit de cel al
programului ntrerupt, diferena fiind legat de modul de tratare, protecie, informaiile accesibile, etc.
27. Devieri i apelarea supervizorului
O deviere semnalizeaz o anomalie n derularea unei instruciuni, care prohibiteaz executarea
instruciunii. Originile pot fi diverse:
date incorecte, instruciune neexecutabil . Devierile pot fi clasificate, ca i ntreruperile, conform cauzelor
care le genereaz. O deviere poate fi suprimat, dar nici intr-un caz retardat. Un apel al
supervizorului (supervisor call, prescurtat SVC, eng., appel au superviseur, fr.) este o instruciune
chemat s provoace o comutare a contextului procesorului. Acest efect este analogic apelrii unei
proceduri, ns modificarea contextului este mai profund,
Destinaia unui apel al supervizorului este de a permite apelarea unei proceduri a sistemului de operare,
pretinznd la drepturi mai mari
28. Exemple de sisteme de ntreruperi
Sistemul de ntreruperi are 5 nivele (n ordinea de descretere a prioritilor): eroare hardware, deviere,
apelare supervizor, extern i intrare-ieire. Fiecrui nivel i corespunde n memoria operativ un cuplu de
amplasamente rezervate cuvintelor de stare vechi i nou. Fiecare nivel conine mai multe cauze de
ntrerupere.
29. Utilizarea devierilor i apelrii supervizorului
Simularea instruciunilor lips. Unele instruciuni din setul de baz de instruciuni ale procesorului pot fi
opionale i, deci, pot lipsi n unele configuraii ale calculatorului. Tentativa executrii unei instruciuni
opionale lips genereaz o drivere de tipul instruciune inexistent. Mecanismul devierilor poate fi utilizat
pentru a realiza prin program instruciunea inexistent n setul de baz. De exemplu, pentru o configuraie
n care operaiile aritmetice n virgul mobil nu sunt disponibile ele pot fi simulate prin apelarea
procedurilor corespunztoare. Aceste proceduri trebuie executate n mod slave pentru a permite tratarea
explicit a erorilor: ele sunt apelate prin ncrcarea cuvntului de stare respectiv. O adres de retur trebuie
s fie pregtit de ctre programul de tratare a devierii n top-ul stivei pentru a asigura returul la
instruciunea care urmeaz instruciunii de operaie aritmetic simulat.
Msurarea capacitii memoriei. Un sistem de operare presupune a fi utilizat pentru diverse configuraii
ale calculatorului. Capacitatea memoriei, numrul i natura dispozitivelor periferice, etc., pot fi diferite.
Sistemul de operare trebuie s se adapteze configuraiei concrete, ca i condiiilor particulare de utilizare
(numr de utilizatori, prioriti, etc.). Crearea unei asemenea versiuni specifice se numete generarea
sistemului de operare. Pentru a reduce frecvena generrilor S.O. unii parametri de configurare pot fi
determinai n mod automat la iniializare.
Gestionarea devierilor de ctre utilizatorul sistemului. Reacia standard la o deviere care are loc n
timpul execuiei unui program utilizator este apelarea unei proceduri de sistem, care provoac emiterea
unui mesaj de eroare, oprirea programului curent i trecerea la programul urmtor.
Este de dorit ca fiecare utilizator s aib posibilitatea s asocieze fiecrei cauze distincte de deviere i o
procedur proprie, tratarea creia ar nlocui reacia standard. Pentru a evita o bucl infinit, o deviere din
aceeai cauz i n interiorul acestei proceduri trebuie s apeleze procedura standard.
Asocierea unei proceduri proc de reluare a cauzei i de deviere se face cu ajutorul unui apel al
supervizorului (SVC asociere_deviere) cu parametrii i i proc.
Pentru trecerea la programul urmtor se va apela o procedur a sistemului de operare, apel realizat prin
ncrcarea unui cuvnt de stare, numit schimbare.
30. Exemple de utilizare a ntreruperilor
Principala utilizare a ntreruperilor este msurarea timpului i administrarea operaiilor de intrare-ieire.
Prezentm mai jos cteva exemple de utilizare a ceasului calculatorului.
procedura iniializare;
intr_ceas_nou:=<activ,master,mascat,adr intr_ceas>;
svc_nou :=<activ,master,mascat,adr tratare_svc >;
dezarmare(intr_ceas);
procedura tratare_svc;
save(zon);
case cod of
apel_lim_timp_ex:
-- parametrii p, q, tratare_eroare
ceas:=q;
cspretur:=svc_vechi;
retur:
dezarmare(intr_ceas);
ncarc_csp(cspretur);
endcase
procedura intr_ceas;
dezarmare(intr_ceas);
ncarc_csp(csperoare);
31. Programarea operaiilor de I/O. Organizarea general
Prin noiunea de intrare-ieire (prescurtat I/E; eng. input/output, I/O; fr. entre-sortie, E/S) numim orice
transfer de informaii din sau spre nucleul calculatorului. Operaiile de I/E semnific:
transferurile de informaii dintre diferite nivele ierarhice ale memoriei,
transferurile de informaii din sau spre mediul exterior (organe periferice locale sau la distan, captoare
sau dispozitive de acionare, alte calculatoare, etc.).
Organizarea general-Periferice, controlere, canale
Un organ de intrare-ieire este un dispozitiv capabil s transfere informaii ntre procesorul sau memoria
calculatorului i un suport extern de informaie. Acest transfer este comandat de ctre procesorul central. n
cel mai simplu caz, o instruciune special a procesorului permite transferarea informaiei ntre suportul
extern i un registru al procesorului, care va fi deci ocupat pe toat perioad transferului informaiei. Odat
cu evoluia calculatoarelor, n scopul unei mai bune utilizri a procesorului s-a ajuns la necesitatea acordrii
unei autonomii organelor de intrare-ieire ncredinndu-le funcii tot mai complicate de nlnuire i
comand, procesorului central lsndu-i-se doar iniiativa de lansare i de control a operaiilor. Din
considerente economice mai apoi s-a trecut la separarea dispozitivelor de comand a perifericelor de
perifericele propriu-zise, pentru ca dispozitivele de comand s poat fi partajate ntre mai multe periferice.
Cteva scheme de organizare a perifericelor sunt prezentate n fig.2.5. Schema (c) este proprie unui
calculator de putere mare, (a) i (b) corespund configuraiilor calculatoarelor de putere mai mic. Precizm
funciile organelor reprezentate n aceast figur.
1) Un canal (sau unitate de schimb) este un procesor specializat n operaiile de intrare-ieire. El poate fi
lansat doar de un procesor central, nu posed ntreruperi, dar poate ntrerupe un procesor central. Setul
de instruciuni ale canalului i permite s acioneze controlerele i perifericele, care-i sunt conectate.
Mini- i microcalculatoarele pot poseda organe, numite Uniti de acces direct la memorie (ADM), care
sunt nite canale simplificate.
2) Un contrler este un dispozitiv de comand adaptat la un tip concret de echipament periferic.
Autonomia sa este limitat de operaii foarte elementare. Destinaia principal a unui controler este de a
permite conectarea a mai multor periferice de acelai tip la un singur controler. Un singur dispozitiv
periferic poate transmite informaii prin intermediul controlerului la un moment de timp dat. n acelai
timp, este posibil executarea simultan a unor operaii pe alte periferice, operaii care nu implic
transferul de informaii (rebobinarea unei bande magnetice, deplasarea braului unui disc, etc.).
Partajarea funciilor ntre periferic i controler depinde de tipul perifericului. De obicei, funciile logice
(nlnuirea i sincronizarea operaiilor, emiterea unor semnale n caz de accident sau terminarea
normal a execuiei) sunt ncredinate controlerului, iar funciile fizice (transferul propriu-zis) perifericului. n programarea intrrilor-ieirilor nu este necesar, de obicei, s se fac o deosebire ntre
un controler i un periferic.
3) Un periferic este un organ capabil s transfere informaii din sau spre un suport extern. Controlerul este
legat de periferic printr-o interfa, care conine un set de funcii (intrare, ieire, semnalizri de
comand i de accident) i o linie de comunicaie, care servete la transferul informaiilor.
C
p
p p
UC: unitate
central
M: memorie
C: canal
ADM: acces
Fig. 2.5.
direct la
Organizarea
intrrilor-ieirilor memorie
Cp: controler
p: dispozitiv
periferic
C
p
p
(
c
)
U
C
(
a
)
C
p
p
U
C Magistral
Magistral
A
M
D
CM C
pp
pp
(
b
)
U
C
Magistral
C
C
M
p
p
p
p
U
C
Un canal poate comanda un singur dispozitiv periferic cu debit ridicat (disc, de ex.) sau poate fi multiplexat
pentru mai multe periferice cu debitul mai mic. ncercarea mai multor procesoare (uniti centrale sau
canale) de a accesa simultan memoria operativ poate genera conflicte. Conflictele sunt reglate de ctre
dispozitivul hardware de accesare, care impune o ordine de acces conform unor prioriti prestabilite.
Canalele au prioritate fa de unitile centrale, deoarece ele trebuie s reacioneze ct se poate de rapid la
evenimentele externe.
32. Metode de comand a perifericelor
Programul, care controleaz funcionarea elementar a unui dispozitiv periferic se numete driver.
Driverul gestioneaz n mod direct interfaa controlerului perifericului, trateaz ntreruperile generate de
acesta, detecteaz i trateaz cazurile de eroare. El este, de obicei, invizibil unui utilizator obinuit al
sistemului, care apeleaz funcii de intrare-ieire prin intermediul unor servicii de nalt nivel, realizate prin
apelri ale supervizorului.
SL
2) scriere pe disc
SD
(canal 1)
3) citire de pe disc
CD
(canal 2)
4) imprimare fizic IF
scriere
_linie S
L
(unitatea central)
(canal 3)
S
D
C
D
tm1
I
F
tm2
(memo
rie)
td
(memo
rie)
(di
sc)
Fig.3.1. Gestionarea
buferizat a unei
imprimante
n realitate, citirea i scrierea pe disc sunt executate pe acelai canal, ceea ce poate impune unele restricii privind simultaneitatea executrii lor. Vom ignora aici
aceste restricii, justificnd mai apoi acest mod de procedare.
Aceste patru activiti sunt n mare msur autonome, or ele sunt executate pe procesoare distincte, cu
programe diferite. Ele nu sunt totui independente, deoarece acceseaz obiecte comune: dou tampoane n
memorie, tm1 i tm2 i un tampon pe disc, td. Pot fi evideniate dou tipuri de condiii, care trebuie
respectate:
1) Condiii, care stabilesc posibilitatea existenei unor activiti
O nregistrare nu poate fi preluat dintr-un tampon nainte de a nu fi depozitat aici. Tampoanele au
capaciti limitate; dac un tampon este ocupat cu nregistrri, care nu au fost nc preluate, este imposibil
depozitarea fr a pierde informaii. Aciunile de depozitare i preluare sunt, deci, supuse unor condiii de
posibilitate de existen, enumerate mai jos.
Activitate
Aciune
Condiie
SL
scriere n tm1
SD
SD
scriere n td
td nu este plin
CD
citire din td
td nu este vid
CD
scriere n tm2
IF
Execuia activitilor modific veridicitatea acestor condiii: astfel, imprimarea unei linii pune n TRUE
condiia tm2 nu este plin.
O activitate, care nu poate executa o aciune, deoarece condiia asociat are valoare FALSE, trebuie s
atepte, adic execuia unei aciuni este retardat pn cnd valoarea logic a condiiei devine TRUE. n
capitolul 2 a fost discutat realizarea acestui mecanism de ateptare i continuare cu ajutorul ntreruperilor.
2) Condiii de validitate a informaiilor partajate
Dac vom examina procesul de accesare a tampoanelor, vom descoperi o alt form de interaciune,
cauzat de posibilitatea de accesare simultan de ctre dou activiti a unui amplsament de memorie.
Astfel, dac SD citete coninutul unei nregistrri din tm1 pe care SL este n curs de a o modifica,
rezultatul acestei citiri risc s fie incoerent, dac nu au fost luate msuri speciale de precauie. Problema
poate fi rezolvat impunnd una din activiti, aflate n conflict, s atepte pn cnd cealalt va termina
accesarea.
Concluziile acestei prime analize:
Lucrarea imprimare tamponat este realizat prin patru activiti simultane, n mare msur autonome,
care coopereaz pentru atingerea scopului final.
Executarea corect a lucrrii impune restricii logice n vederea derulrii acestor activiti. Aceste restricii
pot conduce la ntrzierea execuiei unei activiti, care este obligat s atepte producerea unui eveniment,
provocat de o alt activitate.
36. Gestionarea activitilor paralele. Comanda unui proces industrial
Considerm dou reactoare identice, R1 i R2, care funcioneaz n paralel. Vom examina dou soluii
posibile:
1) utilizarea a dou calculatoare (cte unul pentru fiecare reactor),
2) folosirea unui singur calculator pentru comanda ambelor reactoare.
Prima variant nu prezint nimic nou n raport cu descrierea din capitolul 1. Soluia a doua cere stabilirea
condiiilor suplimentare pentru realizarea sa. Implementarea variantei doi impune verificarea posibilitii
apariiei unor condiii suplimentare. Fie P1, P2, D1, D2 segmentele procedurilor i datelor pentru comanda
celor dou reactoare R1 i R2, memoria principal avnd capacitatea necesar pentru pstrarea acestor
segmente. Programele P1 i P2 sunt executate pe rnd de procesor. Raionnd ca i n capitolul 1,
concluzionm c relaia 2t<T trebuie s fie respectat. Dac acesta va fi cazul, funcionarea reactoarelor
pentru un observator extern pare identic pentru ambele soluii. Trebuie, totui s subliniem, c soluia doi
impune restricii mai severe n ceea ce privete performanele calculatorului (capacitatea memoriei i viteza
de procesare)
Vom examina mai jos modalitile de implementare a soluiei doi.
Partajarea procesorului
ntre dou execuii succesive ale lui P1, procesorul este utilizat de P2, ca rezultat starea sa intern
(coninutul registrelor, cuvntul de stare, contorul ordinal) va fi modificat. Pentru a permite reluarea lui P1,
informaiile sale trebuiesc salvate la terminarea fiecrei secvene de execuie i restabilite la nceperea
execuiei urmtoare. Aceleai afirmaii sunt valabile i n cazul executrii lui P2.
Partajarea programului
Programele P1 i P2, fiind identice, putem pstra doar o singur copie, s-i zicem P, pentru economisirea
memoriei. S examinm condiiile necesare pentru partajarea programului P:
nu este permis modificarea codului programului de execuia sa,
atunci cnd P este executat pentru reactorul Ri (i=1 sau 2), el va accesa segmentul de date Di; aceast
adresare selectiv a datelor va fi realizat de un mecanism care nu modific textul programului.
Un program, existent n exemplar unic, dar care poate fi utilizat pentru executarea mai multor activiti
independente, eventual simultane, se numete program reentrant (reenterabil). Acest mod de utilizare
implic:
invariana textului programului n cursul executrii sale,
desemnarea uniform, de ctre program, a datelor proprii fiecrei activiti.
Printre altele, dac activitile partajeaz un procesor unic, informaiile despre starea acestuia (n particular,
cele care servesc la desemnarea datelor) trebuiesc salvate la fiecare comutare.
S rezumm rezultatele celui de-al doilea exemplu.
Au fost evideniate dou activiti logic independente: comanda reactoarelor R1 i R2. Aceste dou
activiti pot fi puse pe dou maini distincte fr s existe vre-o legtur ntre ele.
Considerente de economie pot impune ca aceste activiti s partajeze resurse fizice i resurse
program comune. Buna funcionare a acestei partajri restricioneaz execuia activitilor
(utilizarea alternativ a procesorului) i modul de utilizare a obiectelor partajate (salvarea
contextului de executare, reentrana programelor).
Ca i concluzie pentru ambele exemple putem evidenia dou momente:
existena unor activiti evolutive, care pot derula simultan,
existena unor relaii ntre aceste activiti: cooperare pentru executarea unor sarcini comune,
concuren n utilizarea resurselor partajate. Aceste relaii sunt determinate de specificaiile de bun
funcionare. Ele se pot traduce n restricii de execuie, care conduc la ntrzieri temporare a
progresrii unei activiti.
ntr-un mod mai riguros ar trebui s adugm aici punctele ntreruptible care pot fi prezente n unele instruciuni de lung durat; o executare a unei
asemenea instruciuni poate fi considerat o suit de mai multe aciuni.
Pentru comoditatea expunerii considerm, c sfritul unei aciuni i nceputul aciunii urmtoare sunt dou evenimente distincte, datele crora sunt diferite,
dei strile corespunztoare sunt identice.
-traiectoria temporal a unei mulimi de procese este irul evenimentelor formate de nceputurile i
sfriturile aciunilor rezultante din executarea programelor acestor procese.
-contextele unor procese diferite pot avea pri comune. Dou procese, contextele crora sunt disjuncte, se
numesc independente; ele nu pot avea interaciuni reciproce. Partea contextului, care aparine unui singur
proces, se numete context privat al procesului dat.
S considerm dou programe distincte P i Q, fiecare avnd n memorie un segment cod i un segment de
date. Numim p i q procesele rezultante din executarea respectiv a acestor dou programe. Executarea
setului (p, q) poate s se produc n diferite moduri, caracterizate de forma particular a traiectoriei sale
temporale. Aceste traiectorii sunt reprezentate n figura 3.2.
Schemele de mai sus pot fi comentate astfel:
schema 1: este executat mai nti tot procesul p, apoi procesul q la fel n ntregime,
schema 2: sunt executate iruri de instruciuni ale procesului p n mod alternativ cu iruri de instruciuni
ale procesului q, i tot aa pn la terminarea ambelor procese,
schema 3: executarea proceselor p i q este simultan; n acest caz sunt necesare dou procesoare.
Pentru compararea acestor scheme de execuie introducem noiunea nivel de observare. Putem considera o
suit de aciuni ale unui proces ca o aciune unic, adic s observm derularea unui proces considernd o
unitate de execuie
mai puin fin dect instruciunea. De exemplu, dac vom redefini noiunea de aciune elementar ca
execuie a unei proceduri, traiectoria procesului va conine doar strile definite de fiecare apel i retur de
procedur. Nivelul de observare cel mai fin (cel al instruciunilor) este numit nivel de baz.
S ne situm mai nti la nivelul de observare la care, prin convenie, executarea complet a fiecrei dintre
programele P i Q reprezint o aciune unic. Definiiile care urmeaz sunt pentru acest nivel.
a) schema de tip 1 este a unei execuii secveniale a lui p i q. Ea este caracterizat de relaiile:
sfrit(q) < nceput(p) sau sfrit(p) < nceput(q)
b) schemele de tip 2 sau 3 sunt scheme de execuie paralel. Ele sunt caracterizate de
sfrit(p) > nceput(q) sau sfrit(q) > nceput(p).
Revenim la nivelul de baz. Putem face o distincie ntre schemele 2 i 3. ntr-adevr, n schema 2, din
considerente de existen a unui singur procesor, la un moment de timp dat doar o singur aciune poate fi
executat, contrar schemei 3. Se va spune c n schema 3 are loc un paralelism real, iar n schema 2 un
pseudo-paralelism. Paralelismul real necesit dou procesoare distincte. Dou observaii importante sunt
necesare:
1) Diferena acestor scheme de execuie este legat de alegerea nivelului de observare. Astfel, la nivelul de
baz, diferena dintre schemele 1 i 2 dispare: ambele sunt secveniale.
2) Alegerea nivelului de baz depinde de fineea fenomenelor, care dorim s le considerm elementare.
Dac trebuie s studiem executarea instruciunilor n pipe-line pe un procesor microprogramat, n
calitate de nivel de baz va fi ales
39. Concurena proceselor. Resurse virtuale
Situaia descris de schemele 1 i 2 nu rezult dintr-o legtur logic ntre p i q, ci doar din existena unui
singur procesor. Ea poate fi caracterizat astfel: fie o mulime de procese contextele crora au un obiect
comun, care poate fi utilizat la un moment de timp dat de un singur proces. Se va spune n acest caz, c
obiectul constituie o resurs critic pentru procesele date sau c procesele sunt n excludere mutual
(excludere reciproc sau concuren) pentru utilizarea unei resurse. n situaia descris, procesorul este o
resurs critic pentru procesele p i q.
Observm c excluderea mutual a unei resurse conduce la serializarea execuiei proceselor concurente,
n cazul unor aciuni, care cer aceast resurs (n exemplul dat, toate aciunile). Schemele 1 i 2 difer doar
prin nivelul de finee la care este executat serializarea.
Funcionarea corect a unei mulimi de procese, care particip la ndeplinirea unei lucrri comune, implic
relaii logice de cooperare (v.3.1.1). Este comod s se separe aceast cooperare de concurena pentru
resursele fizice cu scopul de a simplifica nelegerea i aplicarea celor dou tipuri de relaii. Pentru aceasta
este folosit noiunea de resurse virtuale: fiecrei resurse fizice critice i se asociaz tot attea copii
imaginare (sau virtuale) ale acestei resurse cte procese concurente solicit utilizarea ei. Suntem nevoii s
tratm dou probleme distincte:
1) respectarea relaiilor de cooperare ntre procesele, care, fiecare posed (conceptual) resursele fizice
solicitate i pentru care paralelismul n execuie nu este restricionat de competiia pentru resurse,
2) reglarea problemei de concuren pentru resursele fizice printr-o serializare convenabil a execuiei
proceselor n cauz. Se va spune n acest caz, c realizm o alocare a resurselor fizice.
Introducerea resurselor virtuale are o consecin foarte important pe care o vom ilustra-o prin exemplul
proceselor p i q, definite n 3.2.2.1. S atam fiecrui proces un procesor virtual. Conceptual, totul va
avea loc ca i cum procesele s-ar derula paralel, conform unei scheme, numite logice sau virtuale, analogice
schemei 3 din fig.3.2. Cu toate acestea, trebuie de menionat, c aceast schem logic reprezint doar o
notaie compact pentru mulimea schemelor reale posibile i c ele sunt obligatoriu de forma 1 sau 2 din
considerentele unicitii procesorului. Pentru o schem real i una virtual a unui proces dat este pstrat
doar ordinea de succesiune a evenimentelor (nceputul i sfritul aciunii) i nu sunt pstrate valorile
absolute ale intervalelor de timp, care le separ. n absena altor informaii, nu putem spune nimic apriori
despre ordinea evenimentelor, asociate unor procese distincte. Timpul folosit la reperarea evenimentelor n
schema logic este numit timp logic; relaiile sale cu timpul real sunt prezentate n fig.3.3.
a1
a2
+------+-----------------+------+
b1
b2
procesul p
(timp logic)
+--+-------+---------+ procesul q
a1
a2
+------+---+
+----------+ +----+------+ p
+--+--+
b1
b2
a1
a2
+-----+---------+
+---+
+---+-----------------+------+ p
+--+----+
b1
+---+---------+
b2
Ap : n=n+np procesul q:
Aq : n=n+nq
S realizm decompoziia acestor aciuni n instrucii, notnd prin Rp i Rq registrele locale ale proceselor
p i q respectiv:
procesul p
procesul q
1. load Rp, n
1. load Rq, n
2. add Rp, np
2. add Rq, nq
Exemplul 3.4.Procesul p transmite informaii procesului q scriind ntr-un segment a, consultat de q (se
presupune c aceast transmitere are loc o singur dat). Este necesar s se verifice condiia:
sfrit(scriere(a)) < nceput(citire(a))
Aceast relaie exprim restricia, c citirea lui a de ctre q nu poate ncepe nainte de terminarea scrierii lui
a de ctre p.
Exemplul 3.5.Rendez-vous. Fie N procese p1,..., pN. Definim n programul fiecrui proces un punct, numit
rendez-vous, pe care procesul nu-l poate trece nainte ca alte procese s ajung la punctul lor propriu de
rendez-vous.
Dac programul procesului pi are forma
<debut_i>;
<rendez-vous>
<continuare_i>;
atunci restriciile de sincronizare se vor exprima dup cum urmeaz:
procesul p
procesul q
scriere(a);
<debut_q>;
f:=true;
<continuare_p>
aut(ps) :
ps :
citire(a)
f:=true
A fost introdus variabila de stare f pentru a exprima condiia procesul p a terminat aciunea scriere(a).
Exemplul 3.7:
procesul pi
<debut_i>;
n:=n+1
ps:
<continuare_i>
aut(psi):
n=N (i=1,...,N);
Variabila de stare n este n acest caz numrul procesului sosit n punctul de rendez-vous.
43. Probleme de realizare a sincronizrii
Vom ncerca s implementm sincronizarea specificat de condiiile de depire. Pentru aceasta trebuie s
definim un mecanism de ateptare i s introducem noiunea de evenimente memorizate. Un eveniment
memorizat (e) este o variabil, care poate lua dou valori: sosit i non_sosit, valoarea iniial este nonsosit. Asupra evenimentului memorizat sunt posibile dou operaii, care sunt aciuni indivizibile:
e:=<valoare>-- atribuirea imediat a unei valori
ateptare(e).
Operaia ateptare(e), executat de un proces p, are urmtoarea specificaie:
if e = non_sosit then
starea(p) := blocat -- p este trecut n ateptarea lui e
endif
Cnd e ia valoarea sosit, toate procesele care ateptau e trec n starea activ.
Vom ncerca acum s realizm cu ajutorul acestui mecanism sincronizarea pentru cele dou exemple.
var e : eveniment memorizat;
Exemplul 3.8.
procesul p
procesul q
scriere(a);
<debut_q>;
e:=sosit;
ateptare(e);
<continuare_p>
citire(a)
Analiza acestui sistem (care nu conine alte variabile de stare, dect evenimentul memorizat e) poate fi
fcut enumernd traiectoriile temporale posibile. Aceast analiz arat, c sincronizarea este corect
atunci cnd operaiile asupra evenimentului memorizat sunt indivizibile.
var e : eveniment memorizat;
Exemplul 3.9.
n : integer init 0;
procesul pi
<debuti>;
(A) n:=n+1;
(B) if n<N then
ateptare(e)
else
e:=sosit
endif
<continuarei>
O analiz mai atent, analogic celei din exemplul din 3.2.2.3, ne arat c acest program este incorect.
Notnd un registru local al procesului i prin Ri, aciunile (A) i (B) pot fi descompuse dup cum urmeaz:
(1)
load
Ri, n
(2)
ai Ri, 1
-- adunare imediat
(3)
(4)
br () etichet
-- salt dac Ri N
<ateptare (e)>
...
etichet :
...
Presupunem, c toate proceselor sunt n ateptarea punctelor lor de rendez-vous, cu excepia a dou, notate
prin pj i pk. Dac pj i pk vor fi executate pe traiectoria temporal (1j, 1k, 2j,...), atunci fiecare va atribui lui
n valoarea final N-1 i se va bloca, drept rezultat toate procesele se vor bloca pentru un timp indefinit.
Reieind din analiza de mai sus putem concluziona, c implementarea condiiilor de sincronizare nu poate
fi corect realizat numai cu ajutorul operaiilor de ateptare. Consultarea i modificarea variabilelor de
stare, care intervin n aceste condiii, trebuie s fie executate n regim de excludere reciproc. Observaia
dat ne impune s introducem un mecanism de sincronizare, care n mod automat ar asigura acest regim de
funcionare.
44. Monitorul mecanism de sincronizare. Definiii. Exemple de utilizare
Un monitor este constituit dintr-o mulime de variabile de stare i o mulime de proceduri, care utilizeaz
aceste variabile. Unele dintre aceste proceduri, numite externe, sunt accesibile utilizatorilor monitorului;
numele acestor proceduri sunt numite puncte de intrare ale monitorului. Procesele, care utilizeaz
monitorul pentru a se sincroniza, nu au acces direct la variabilele de stare. Monitorul poate fi utilizat doar
prin apelarea procedurilor sale externe; acestea permit blocarea sau deblocarea proceselor conform
specificaiilor problemei. Condiiile de blocare sau deblocare sunt exprimate ca funcie ale variabilelor de
stare, iar mecanismul de execuie a monitorului garanteaz manipularea acestor variabile n regim de
excludere mutual. n fine, un monitor conine un fragment de cod de iniializare, executat o singur dat la
crearea monitorului.
Blocarea i deblocarea proceselor se exprim, n procedurile monitorului, prin intermediul unor condiii. O
condiie este declarat ca i o variabil, dar nu are valoare: o condiie c poate fi utilizat doar prin
intermediul a trei operaii sau primitive, efectul crora este descris mai jos (prin p am notat procesul, care le
execut)
c.ateptare
c.vid
: funcie cu valori booleene (true, dac nu exist nici un proces n ateptarea lui c, altfel false)
c.semnalizare: if non c.vid then <deblocarea proceselor care sunt n ateptarea lui c> endif
Procesele, care sunt n ateptarea unei condiii c, sunt grupate ntr-un fir de ateptare asociat lui c. Putem
spune, c o condiie furnizeaz proceselor un instrument de desemnare a unui astfel fir de ateptare.
Un proces deblocat de c.semnalizare i reia execuia de la instruciunea, care urmeaz imediat primitivei
c.ateptare, care-l blocase. Necesitatea asigurrii excluderii reciproce pentru variabilele de stare impune o
restricie suplimentar mecanismelor de deblocare: atunci cnd un proces p deblocheaz un proces q printro operaie de semnalizare, p i q nu pot fi meninute simultan active. Se va impune blocarea lui p pn n
momentul n care q, la rndul su, se va bloca sau va prsi monitorul. Pentru evitarea unei blocri
indefinite a lui p este necesar ca operaia de transfer a comenzii de la p la q s fie atomar (indivizibil) i
se va garanta, c un proces care a fost temporar blocat este deblocat de operaia semnalizare nainte ca un
nou proces s poat executa o procedur a monitorului.
3.3.3.2. Exemple de utilizare
Exemplul 3.10.
var
sinc: monitor;
fact:
boolean;
term: condiie;
procedura terminare_scriere;
begin
fact:=true;
term.semnalizare
end
procedura debut_citire;
if non fact then
term.ateptare
endif
begin -- iniializare
fact := false
end
end sinc
Monitorul este utilizat dup cum urmeaz:
procesul p
scriere(a);
procesul q
<debut_q>
sinc.terminare_scriere;
<continuare_p>
Exemplul 3.11.
sinc.debut_citire;
citire(a);
rendez-vous : monitor;
var n : integer;
toi_sosii
: condiie;
procedura sosire;
begin
n := n+1;
if n < N then
toi_sosii.ateptare --nu au sosit toate procesele
endif
toi_sosii.semnalizare
-- a sosit i ultimul
end
begin -- iniializare
n:=0
end
end rendez_vous
Programul procesului pi va fi de forma:
procesul pi
<debut i>
rendez_vous.sosire;
<continuare i>
Este foarte important s nelegem funcionarea sincronizrii: procesul, care sosete ultimul la rendez_vous,
execut toi_sosii.semnalizare i deblocheaz unul dintre procesele, care sunt n starea ateptare. Acesta, la
rndul su, execut toi_sosii.semnalizare, deblocnd urmtorul proces i aa mai departe.
45. Implementarea sincronizrii. Probleme-tip
Experiena demonstreaz, c problemele de sincronizare logic ntlnite n practic pot fi reduse, n marea
lor majoritate, la combinaia unui numr mic de situaii elementare, schemele de soluionare ale crora sunt
cunoscute. Seciunile 3.4.2 3.4.5 sunt consacrate studierii acestor probleme-tip, utiliznd instrumentarul
de baz, pus la dispoziie de monitoare. Problemele-tip sunt urmtoarele:
accesarea de ctre o mulime de procese a unei resurse partajate comune,
comunicarea ntre procese,
gestionarea perifericelor i intrrilor-ieirilor tamponate,
sincronizare temporal.
46. Administrarea unei resurse partajate
Considerm o resurs (fizic sau logic) partajat de o mulime de procese. Utilizarea acestei resurse
trebuie s respecte nite reguli de utilizare, destinaia crora const n garantarea unor proprieti
specificate sau restricii de integritate. Aceste restricii sunt specificate pentru fiecare resurs. O
modalitate de garantare a respectrii regulilor de utilizare a unei resurse const n adoptarea urmtoarei
scheme:
modul de folosire a resursei presupune utilizarea obligatorie a procedurilor de acces asociate resursei;
orice tentativ de utilizare, care nu respect acest mod este detectat automat,
procedurile de accesare sunt grupate ntr-un monitor, sau mai multe, programul cruia impune
respectarea restriciilor de integritate.
Cel mai simplu caz este acela al unei resurse pentru care singura restricie de integritate este de a fi utilizat
n excludere reciproc. Simpla grupare a procedurilor sale de acces ntr-un monitor unic garanteaz
respectarea acestor restricii.
47. Alocarea resurselor banalizate
Considerm o resurs pentru care exist un numr fix de N exemplare. Un proces poate accesa la cerere n
uniti din cele N, le poate utiliza i apoi elibera. O unitate, folosit de un proces, se numete alocat
procesului, care o utilizeaz, pentru toat perioada de la accesare pn la eliberare. Toate unitile sunt
echivalente din punctul de vedere al proceselor utilizatoare, vom mai zice c resursa este banalizat.
Zonele-tampon din memoria principal sau pe disc, unitile de band magnetic, etc. sunt exemple de
resurse banalizate.
Vom admite urmtoarele reguli de utilizare:
o unitate poate fi alocat la un moment de timp dat doar unui singur proces,
o unitate poate fi alocat unui proces, care cere alocarea, doar dac ea este liber (nu este alocat nici
unui proces),
o operaie de eliberare este aplicat totdeauna ultimelor resurse, achiziionate de procesul care execut
eliberarea,
o cerere de alocare este blocant n caz de eec (numr insuficient de uniti libere).
Definim dou proceduri cerere i eliberare ale unui monitor. Utilizarea resursei are loc conform schemei
de mai jos.
ps:resurse.cerere(n); -- cerere pentru n uniti
-- ateptare n caz de eec
<utilizarea unitilor primite>
resurse.eliberare(n) -- eliberarea resurselor
Condiia de sincronizare se va scrie pentru orice proces:
aut(ps) : n nlibere
Prima form a unui monitor resurse se va obine utiliznd direct condiia de sincronizare:
resurse: monitor;
var nlibere : integer;
disp
: condiie;
procedura cerere(n);
begin
while n>nlibere do
disp.ateptare;
endwhile;
nlibere:=nlibere-n
end;
procedura eliberare(n);
begin
nlibere:=nlibere+n;
disp.semnalizare
-- deblocare n lan
end;
begin -- iniializare
nlibere:=N
end
end resurse
Nu a fost fcut nici o ipotez despre ordinea proceselor n firul de ateptare al condiiei disp. Drept
consecin, la fiecare eliberare vor fi deblocate toate procesele. Este o soluie greoaie i poate fi foarte
costisitoare, dac exist multe procese. Este preferabil s se programeze n mod explicit administrarea
firului de ateptare a cererilor, ceea ce oblig s avem cte o condiie distinct pentru fiecare proces.
Pentru elaborarea programelor vom introduce un tip discret proces, variabilele cruia permit desemnarea
proceselor.
resurse : monitor
type element : struct
lungime : integer
proc
: proces
end;
var nlibere : integer;
disp
:array[proces] of condiie;
e.proc:=p;
introducere(e,f);
disp[p].ateptare
endif;
nlibere:=nlibere-n
end;
procedura eliberare(n);
var e: element;
begin
nlibere:=nlibere+n;
while primul(f).lungime nlibere do
extragere(e,f);
Fie fich un monitor care asigur respectarea acestor restricii. Vom impune urmtoarea form a acceselor la
fiier:
proces cititor proces scriitor
fich.debut_citire;
fich.debut_scriere;
fich.terminare_citire; fich.terminare_scriere;
Procedurile debut_citire, terminare_citire, debut_scriere, terminare_scriere trebuie s asigure
respectarea restriciilor de mai sus. Vom implementa aceste restricii autoriznd depirile; pentru aceasta
este necesar s fie precizate prioritile ntre cititori i scriitori.
Cu titlu de exemplu, presupunem c cititorii au prioritate n faa redactorilor (o scriere nu va fi autorizat,
dac exist cititori n ateptare). Definim urmtoarele variabile de stare:
scr = o scriere este n curs (valoare boolean)
nc = numrul de cititori n ateptare sau n curs de citire
n acest caz, condiiile de depire se vor exprima dup cum urmeaz:
aut(citire) :
scr=false
scr
: boolean;
nc
: integer;
end
procedura terminare_scriere;
begin
scr:=false;
if nc>0 then -- prioritate cititorilor care ateapt
c_cit.semnalizare
else
c_scr.semnalizare
endif
end
begin -- iniializare
scr:=false;
nc:=0
end
end fich
Pot fi definite i programate i alte reguli de prioritate.
49. Comunicarea ntre procese
Procesele pot comunica prin accesarea unei mulimi de variabile comune. Acest mod de comunicare este
slab structurat i ineficace, deoarece el trebuie s asigure excluderea reciproc a variabilelor. Este utilizat
doar n cazuri speciale, cum ar fi un nucleu de sincronizare, unde excluderea mutual global este redus la
secvene scurte i bine protejate. Pentru cazuri generale sunt utilizate alte moduri de comunicare. Vom
prezenta mai nti o schem de baz pentru comunicarea prin mesaje - modelul productorului i
consumatorului, realizat cu ajutorul monitoarelor (3.4.3.1). O alt posibilitate, descris n 3.4.3.2, const n
a considera operaiile de comunicare ca un fel de mecanisme primitive de sincronizare. n 3.4.3.3
prezentm o aplicaie frecvent de comunicare modelul client-server.
50. Modelul productorului i consumatorului
O schem uzual de comunicare este cea n care un proces (productorul) trimite mesaje unui alt proces
(consumatorul), utiliznd un tampon n memoria comun. Mesajele sunt de lungime fix i capacitatea
tamponului este de N mesaje.
Specificaiile comunicaiei sunt urmtoarele:
un mesaj dat poate fi preluat doar o singur dat dup ce a fost depozitat n tampon,
un mesaj nu trebuie s poat fi pierdut; dac tamponul conine N mesaje nepreluate, nu pot fi depozitate
aici mesaje suplimentare,
o operaie imposibil (depozitare ntr-un tampon plin sau preluare dintr-un tampon vid) blocheaz
procesul, care ncearc s o execute.
Condiiile de depire pot fi exprimate dup cum urmeaz, notnd prin n numrul de mesaje din tampon,
care nu au fost nc preluate:
aut(depozitare) : n < N
proces consumator
...
produce(mesaj_emis);
tampon.preluare(mesaj_recepionat);
tampon.depozitare(mesaj_emis);
consumator(mesaj_recepionat);
: 0..N;
end
end tampon
Procedurile introducere(m) i preluare(m) definesc politica de gestionare a tamponului i reprezentarea
intern a mesajelor. Un caz frecvent este acela n care mesajele sunt reprezentate de elementele succesive
ale unui tablou, administrat n mod circular. n acest caz mesajele sunt preluate n ordinea depozitrii.
Procedurile de gestionare a tamponului se vor scrie astfel:
type mesaj : <descrierea formatului mesajelor>
ptr
: 0..N-1;
Distrugerea unui proces de la care alte procese ateapt un mesaj sau un rspuns: procesele n ateptare
sunt blocate i recepioneaz un cod de eroare.
Ultima situaie nu este totdeauna detectabil. O tehnic uzual const n stabilirea unui interval de timp
maxim de ateptare a unui mesaj i deblocarea procesului care ateapt la expirarea acestui interval (v.
3.4.5).
Vom ilustra prin cteva exemple reprezentative utilizarea acestor mecanisme de comunicare.
Exemplul 3.12.
Sistemul de operare Thoth [8]. n acest sistem comunicarea folosete desemnarea
direct i sincronizarea prin rendez-vous. Mesajele sunt de lungime constant. Sunt utilizate patru
primitive:
id:=send(message, id_dest)
emite procesului id_dest un mesaj; blocheaz emitorul pn la primirea unui rspuns, transmis n
message. Aceast primitiv indic identitatea procesului care a transmis rspunsul (sau nil, dac
destinatarul nu exist).
id:=receive(message, id_orig)
recepioneaz un mesaj; procesul origine poate s nu fie specificat. Valoarea transmis este identitatea
emitorului.
reply(message, id_orig, id_dest)
trimite un rspuns destinatarului specificat (care trebuie s-l atepte); nu este blocant; fr consecine,
dac rspunsul nu era ateptat.
forward(message, id_orig, id_dest)
aceast operaie non blocant este utilizat de un proces dup recepionarea unui mesaj trimis de ctre
id_orig, pentru ca s impun mesajul s ajung la id_dest, care are acum obligaia de a rspunde lui
id_orig.
Exemplul 3.13.
Sistemul de operare Unix [9]. n sistemul Unix comunicarea ntre procese utilizeaz
tampoane, numite pipes (tuburi), administrate conform schemei productor-consumator. Mesajele
transmise sunt caractere. Un pipe (tub) leag un emitor i un receptor, conexiunea fiind stabilit dinamic.
Exemplul 3.14.
Rendez-vous n limbajul de programare Ada [10, 11]. Limbajul Ada permite definirea
proceselor. Forma sintactic a comunicrilor ntre procese este apelarea procedurii, ns transmiterea
parametrilor i a rezultatelor are loc conform principiului de transmitere a mesajelor cu rendez-vous.
Recepionarea poate fi condiionat (un apel este acceptat doar dac o condiie specificat este satisfcut)
i exist posibilitatea de ateptare multipl.
52. Aplicaii : relaia client-server
O aplicaie curent a comunicrilor ntre procese este relaia client-server. Un proces server are n arj
ndeplinirea unor servicii (executarea unui program predefinit) proceselor client. Pentru aceasta poate fi
utilizat urmtoarea schem:
procesul server
procesul client
ciclu poart_serviciu.emitere(cerere)
poart_serviciu.recepionare(cerere)
<executare serviciu>
...
[poart_client.emitere(rezultat)]
endciclu
...
[poart_client.recepionarere(rezultat)]
sfr_schimb_i.ateptare;
-- ntrerupere demascat
tm2[coad] := l;
l := tm2[top];
n monitorul tampon_disc operaiile de depozitare i preluare sunt intrri-ieiri, care utilizeaz monitorul de
gestionare a discului:
procedura intrare(l:linie);
disc.scriere(l,td[coad]);
coad := coad+1 mod Ndisc
procedura ieire(var l:linie);
disc.scriere(l,td[top]);
top := top+1 mod Ndisc
Programul de intrare-ieire este realizat prin cooperarea a patru procese programul crora este prezentat
schematic mai jos (trei procese ale sistemului de operare i procesul utilizator). Pentru a simplifica
expunerea au fost omise secvenele de tratare a erorilor i am admis, c sistemul funcioneaz n regim
permanent fr limitarea numrului de linii la imprimare. Programele folosesc trei monitoare de gestionare
a perifericelor (tampon1, tampon2 i tampon_disc) i dou monitoare de gestionare a perifericelor (impr i
disc), construite n baza modelului perif, prezentat n 3.4.4.1
proces imprimare linie
proces scriere_disc
proces citire_disc
tampon1.preluare(l);
impr.scriere(l);
tampon_disc.scriere(l);
endciclu
endciclu
tampon_disc.citire(l);
tampon2.depozitare(l);
endciclu
Vom utiliza a doua metod de funcionare. Unitatea de timp folosit este perioada ceasului.
Pentru rezolvarea problemelor principale de sincronizare temporal poate fi folosit primitiva
suspendare(t), care are ca efect blocarea procesului apelant pentru o durat (fizic) egal cu t uniti de
timp. Prezentm principiul de realizare a acestei primitive cu ajutorul unui ceas.
Pentru rezolvarea acestei probleme vom fi nevoii s ntreinem:
valoarea absolut a timpului (ora absolut), care msoar la orice moment timpul trecut de la o
instan iniial,
un registru, adic o list a proceselor care ateapt deblocarea, ordonat conform timpului absolut de
deblocare.
Toate procesele, care apeleaz primitiva suspendare(t) sunt inserate n registru n poziia, care corespunde
orei sale absolute de deblocare.
Numim ora_de_baz ora absolut a ultimei nnoiri a ceasului, adic a ultimei iniializri a contorului; fie
t_at ultima valoare ncrcat. Ora absolut exact este dat la fiecare moment de timp de relaia
ora_exact = ora_de_baz + t_at - contor
(t_at - contor este timpul care s-a scurs dup ultima nnoire a contorului). De la o ntrerupere de ceas (la
trecerea contorului prin 0), dup ultima nnoire s-a scurs un timp egal cu t_at; ora_de_baz poate, deci, fi
iniializat conform relaiei
ora_de_baz := ora_de_baz + t_at
Variabila ora_de_baz, odat iniializat, va fi corect ntreinut cu condiia ca registrul s nu fie nicicnd
vid; n caz general aceast condiie va fi asigurat introducnd un proces, numit paznic:
procesul paznic
ciclu
suspendare(tmax)
endciclu
n care tmax este un interval foarte mare de timp, paznicul rmnnd pentru toat perioada de lucru n
coada registrului.
Mecanismele descrise sunt realizate ntr-un monitor numit ceas, care are dou intrri: procedura
suspendare (apelat prin ceas.suspendare(t)) i procedura tratare_ntrerupere, pentru tratarea ntreruperii
de ceas (trecerea contorului prin zero). Registrul este realizat cu ajutorul unui fir de ateptare, care conine
descriptorii proceselor. Un descriptor este format din numele procesului i timpul absolut de deblocare;
firul de ateptare este ordonat n ordinea creterii timpului deblocrii.
Presupunem, c ntreruperea de ceas activeaz un proces, unica activitate a cruia const n apelarea
procedurii ceas.tratare_ntrerupere.
ceas: monitor;
type descriptor: struct
i
: proces;
ora_debl
: integer
end;
Problema ar fi uor de rezolvat, dac fiecare proces ar dispune de un ceas propriu: ar fi suficient s se introduc n contor valoarea t i s se atepte ntreruperea
la trecerea prin zero. Realizarea primitivei suspendare cu ajutorul unui ceas unic comun presupune ataarea fiecrui proces a unui ceas virtual.
: array[proces] of condiie;
intrare(proc,fir)
-- ordonare de ora_deblocrii
if proc=primul(fir) then
t_at:=contor:=durata;
ora_de_baz:=ora_exact;
endif;
deblocare[p].ateptare
end;
procedura tratare_ntrerupere; -- contor n zero
var proc: descriptor;
delta_t:integer;
begin
ieire(proc,fir);
ora_de_baz := ora_exact+t_at;
if vid(fir) then
delta_t := tmax
else
delta_t := primul(fir).ora_deblocrii ora_de_baz;
endif;
t_at := contor := delta_t; -- deblocarea viitoare
deblocare[proc.i].semnalizare
end;
begin
ora_de_baz := <ora_iniial>;
contor := t_at := tmax;
intrare(paznic,fir)
end
end ceas
Metoda de mai sus (ntreinerea unui registru i a orei absolute) este utilizat pentru realizarea programelor
de simulare discret. Un atare program realizeaz un model n care diferite procese, executate n regim
pseudo-paralel, reprezint activiti care se deruleaz n paralelism real. Timpul utilizat este un timp
simulat, adic o variabil, care reprezint trecerea timpului fizic, respectnd proporionalitatea intervalelor
timpului simulat cu intervalele corespunztoare ale timpului fizic.
57. Gestionarea dinamic a proceselor
Doar n sistemele cele mai simple procesele sunt n numr constant i create odat pentru totdeauna la
iniializarea sistemului. n sistemele concurente, mai ales n cele interactive, procesele sunt comandate
dinamic. Astfel, n Multics, un proces nou este creat odat cu admiterea unui nou utilizator; n Unix, la
executarea fiecrei comenzi. Primitivele de creare i distrugere a proceselor pot fi puse n arja sistemului
de operare sau la dispoziia utilizatorilor. Crearea unui proces presupune alocarea resurselor i iniializarea
contextului, elementele cruia au fost specificate n 3.2.1. Distrugerea unui proces elibereaz toate resursele
care i-au fost alocate.
Primele primitive, propuse pentru gestionarea dinamic a proceselor, au fost fork i join. Istoric i
cronologic, aceste operaii au fost introduse pentru organizarea executrii paralele a programelor pe un
sistem multiprocesoral, noiunea de proces nefiind nc clar. Vom descrie cteva variante ale acestor
primitive.
Fie P o procedur. Instruciunea
id := fork(p),
executat de un proces p (printe), creaz un proces nou q (fiul), care va fi executat paralel cu p. Primitiva
fork prezint ca rezultat identificatorul lui q (sau nil, dac crearea este imposibil). Contextul iniial al lui q
este o copie a lui p, mai puin contorul ordinal, care este fixat la prima instruciune a lui p. Procesul fiu se
termin cu o primitiv, numit exit sau quit, care provoac dispariia sa. Dup ce fork creaz un proces fiu
q, primitiva join q permite procesului printe s fixeze un punct de rendez-vous cu acest fiu. Executarea lui
join q blocheaz procesul printe pn cnd q nu va executa exit. Primitivele fork i join au avantajele i
dezavantajele instruciunii go to din programarea secvenial.
Exemplul 3.15.
n sistemul de operare Unix crearea unui proces poate fi realizat de ctre interpretorul limbajului de comand (shell) sau cu ajutorul
instruciunii fork() de un program. Ultima situaie este prezentat schematic n fig.3.4.
procesul 2
procesul 1
copie
date
date
stiv
stiv
procesul fiu
procesul printe
procesul printe
procesul fiu
if (fork() == 0)
if (fork() == 0)
else
codul procesului printe
returnare 0
Altfel spus, n Unix primitiva fork (fr parametri) creeaz un proces al crui spaiu de lucru este o copie a
spaiului de lucru a creatorului, inclusiv i contorul ordinal. Diferena poate fi determinat consultnd
valoarea returnat de primitiv (0 pentru fiu; identificatorul fiului sau nil pentru printe). O primitiv wait
permite printelui s atepte terminarea execuiei unuia dintre programele fiu (fr a putea alege care
anume, dac exist mai multe). Un proces termin execuia sa cu primitiva exit. Primitiva exec(p) permite
unui proces s schimbe contextul, apelnd o procedur specificat de p.
La lansarea Unix-ului sunt create dou procese: procesul numit Swaper, care administreaz memoria, cu
pid=0 i procesul Init cu pid=1, care creeaz toate celelalte procese.
Ilustrm folosirea primitivelor fork i exec:
...
id := fork();
if id = 0 then -- eu sunt fiul
exec(p)
-- programul fiului
if id = -1 then
<tratare eroare>
else
<programul printelui>
endif
endif
Primitiva wait este utilizat dup cum urmeaz:
id := wait(cod)
...
Prioritatea firului poate fi modificat dinamic. Firele interactive, care au prioritatea Normal, sunt executate
n mod deosebit de ctre sistem, prioritatea acestor fire fiind majorat, atunci cnd procesul, care le-a
generat, se afl n planul central (foreground). n rezultat, aplicaia curent reacioneaz mai repede la
cererile utilizatorului.
59. Necesitatea sincronizrii n Windows
Cnd un proces este creat n mod automat este creat firul principal al acestuia. Acest fir poate crea n timpul
execuiei alte fire, care la fel pot crea fire noi i aa mai departe. Timpul de procesor fiind repartizat ntre
fire, fiecare fir lucreaz n mod independent.
Toate firele unui proces mpart resursele comune, de exemplu, spaiul de adrese al memoriei operative sau
fiierele deschise. Aceste resurse aparin ntregului proces, deci i fiecrui fir. Fiecare fir poate s utilizeze
aceste resurse fr nici un fel de restricii. n realitate, din cauza multitaskingului controlat (preemptive
multitasking - la orice moment de timp sistemul poate ntrerupe execuia unui fir i transmite controlul unui
alt fir), se poate ntmpla ca un fir s nu fi terminat nc lucrul cu o resurs comun oarecare, iar sistemul
s treac la un alt fir, care utilizeaz aceeai resurs. Rezultatele pot fi imprevizibile. Asemenea conflicte se
pot produce i n cazul unor fire, care aparin chiar unor procese diferite. Problema poate s apar
ntotdeauna cnd dou sau mai multe fire folosesc o resurs comun. Este necesar un mecanism de
coordonare a lucrului firelor cu resurse comune. n Windows acest mecanism se numete sincronizarea
firelor (thread synchronization).
60. Structura mecanismului de sincronizare n Windows
Mecanismul de sincronizare este un set de obiecte ale sistemului de operare Windows, create i gestionate
program, comune pentru toate firele sistemului (unele pentru firele unui singur proces) i utilizate pentru
coordonarea accesului la resurse. n calitate de resurse pot fi toate obiectele, care pot fi accesate de dou i
mai multe fire un fiier pe disc, un port, un articol al unei baze de date, o variabil global a unui
program, accesibil firelor unui singur procesor, un obiect al dispozitivului interfeei grafice (Graphic
Device Interface), etc.
De obicei, sunt utilizate mecanismele (obiectele) de sincronizare, introduse mai sus: excluderea mutual
(mutex), secia critic (critical section), eveniment memorizat (event) i semaforul (semaphore), fiecare
realiznd metoda proprie de sincronizare. n calitate de obiecte sincronizate pot fi chiar procesele sau firele
(cnd un fir ateapt terminarea execuiei unui proces sau a unui alt fir), fiierele, dispozitivele de
comunicaie, etc.
Sensul mecanismelor de sincronizare const n faptul, c fiecare poate s fie n starea set. Pentru fiecare
mecanism de sincronizare aceast stare poate s aib sens propriu. Firele pot s testeze starea curent a
mecanismului de sincronizare i/sau s atepte modificarea acestei stri, coordonndu-i n acest fel
aciunile proprii. Este foarte important s se sublinieze, c atunci cnd un fir lucreaz cu mecanismele de
sincronizare (le creeaz, le modific starea) sistemul nu ntrerupe execuia firului, pn nu va fi terminat
aceast aciune, adic toate operaiile finite din mecanismele de sincronizare sunt atomare (nu pot fi
ntrerupte).
Menionm de asemenea, c nu exist nici o legtur real ntre mecanismele de sincronizare i resurse.
Mecanismele de sincronizare nu pot interzice accesul nedorit la o resurs, ele doar indic firului momentul
cnd acesta poate accesa resursa, sau cnd acesta trebuie s atepte (de exemplu, un semafor la o intersecie
doar indic cnd este permis trecerea. Cineva poate trece pe rou, dar consecinele pot fi grave).
fire, iar evenimentele cu resetare automat sunt utilizate pentru informarea unui anumit fir, celelalte
rmnnd n ateptare.
Funcia CreateEvent creaz un obiect-eveniment, funcia SetEvent seteaz evenimentul n starea set, iar
funcia ResetEvent reseteaz evenimentul. Funcia PulseEvent seteaz evenimentul, iar dup
semnalizarea firelor, care erau n ateptare (toate n cazul resetrii manuale i doar unul la resetarea
automat), reseteaz obiectul. Dac nu exist fire n ateptare, PulseEvent doar reseteaz obiectul, fr
semnalizare.
64. Semafoarele
Un obiect-semafor este n ultim instan un mutex cu contor. Acest obiect permite s fie ocupat de un
numr anume de fire, dup care ocuparea va fi posibil numai dac unul din fire va elibera semaforul.
Semafoarele sunt utilizate pentru a limita numrul de fire, care lucreaz simultan cu resursa. La iniializare
se specific numrul maxim de fire, la fiecare ocupare valoarea contorului semaforului scade.
65. Seciunile critice
Obiectul-seciune critic permite programatorului s evidenieze un fragment de cod n care firul obine
acces la o resurs partajat, prentmpinnd utilizarea resursei de mai muli utilizatori. Pentru a utiliza
resursa firul va intra mai nti n seciunea critic (apelarea funciei EnterCriticalSection). Dac intrarea a
avut loc, nici un alt fir nu va avea acces la aceeai seciune critic, execuia acestuia fiind suspendat.
Reluarea se va produce n momentul n care primul fir prsete seciunea critic (funcia
LeaveCriticalSection). Diferena de mutex const n faptul c seciunea critic este utilizat numai pentru
firele unui singur proces.
Cu ajutorul funciei TryEnterCriticalSection se poate stabili, dac seciunea critic este liber. Utiliznd
aceast funcie, un proces, fiind n ateptarea resursei, poate s nu se blocheze, ndeplinind operaii utile.
66. Protejarea accesrii variabilelor
Exist o serie de funcii, care permit lucrul cu variabilele globale ale tuturor firelor, fr a ne preocupa de
sincronizare, deoarece aceste funcii singure rezolv problema sincronizrii. Aceste funcii sunt
InterlockedIncrement, InterlockedDecrement, InterlockedExchange, InterlockedExchangeAdd i
InterlockedCompareExchange. De exemplu, funcia InterlockedIncrement incrementeaz valoarea unei
variabile pe 32 bii cu o unitate.
67. Sincronizarea n MFC
Biblioteca MFC conine clase speciale pentru sincronizarea firelor (CMutex, CEvent, CCriticalSection i
CSemaphore). Aceste clase corespund obiectelor de sincronizare WinAPI i sunt derivate de la clasa
CSyncObject. Pentru utilizarea acestor clase trebuie consultai constructorii i metodele lor Lock i
Unlock. n principiu, aceste clase sunt doar un fel de ambalaj pentru obiectele de sincronizare.
O alt modalitate de utilizare a acestor clase const n crearea aa numitelor clase thread-safe. O clas
thread-safe reprezint o anumit resurs n program. Tot lucrul cu resursa este realizat numai prin
intermediul acestei clase, care conine toate metodele necesare. Clasa este proiectat n aa mod, ca
metodele ei s rezolve problema sincronizrii, adic n cadrul aplicaiei s apar ca o simpl clas. Obiectul
de sincronizare MFC este inclus n aceast clas n calitate de membru privat i toate funciile clasei, care
realizeaz accesarea resursei, i coordoneaz lucrul cu acest membru.
Utiliznd funciile Lock i Unlock clasele de sincronizare MFC pot fi utilizate direct, iar n mod indirect
prin funciile CSingleLock i CmultiLock.
68. Exemplu de sincronizare n Windows
Prezentm un exemplu simplu de lucru cu obiectul de sincronizare mutex [22]. Pentru simplitate a fost
utilizat o aplicaie Win32 de consol, dei nu este obligator.
#include <windows.h>
#include <iostream.h>
void main()
{
DWORD res;
// crem obiectul excludere mutual
HANDLE mutex = CreateMutex(NULL, FALSE, "NUME_APLICATIE-MUTEX01");
// dac obiectul exist deja, CreateMutex va returna descriptorul obiectul existent,
// iar GetLastError va returna ERROR_ALREADY_EXISTS
// timp de 20 s ncercm s ocupm obiectul
cout<<"ncerc s ocup obiectul...\n"; cout.flush();
res = WaitForSingleObject(mutex,20000);
if (res == WAIT_OBJECT_0) // dac ocupare s-a terminat cu succes
{
// ateptm 10 s
cout<<"L-am prins! Ateptare 10 secunde...\n"; cout.flush();
Sleep(10000);
// eliberm obiectul
cout<<"Acum eliberm obiectul\n"; cout.flush();
ReleaseMutex(mutex);
}
// nchidem descriptorul
CloseHandle(mutex);
}
Pentru a controla modul de funcionare a mecanismului de excludere mutual se vor lansa dou instane ale
acestei aplicaii. Prima instan va ocupa obiectul imediat i-l va elibera doar peste 10 secunde. Numai
dup aceasta instana a doua va reui s ocupe obiectul. n acest exemplu obiectul de sincronizare este
folosit pentru sincronizarea proceselor, din care cauz n mod obligatoriu trebuie s aib nume.
69. Utilizarea seciunilor critice n Windows
n acest caz seciunile critice sunt utilizate pentru a permite la un moment de timp dat accesul la unele date
importante unui singur fir al aplicaiei, celelalte fire fiind blocate. De exemplu, fie variabila m_pObject
i cteva fire, care apeleaz metodele obiectului referit de m_pObject. Presupunem c aceast variabil
din timp n timp i poate schimba valoarea, valoarea 0 nu este interzis. Fie urmtorul fragment de cod:
// Firul #1
void Proc1()
{
if (m_pObject)
m_pObject->SomeMethod();
}
// Firul #2
void Proc2(IObject *pNewObject)
{
if (m_pObject)
delete m_pObject;
m_pObject = pNewObject;
}
n acest exemplu exist pericolul potenial de apelare m_pObject->SomeMethod() dup ce obiectul a
fost distrus cu ajutorul delete m_pObject, deoarece n sistemele de operare cu multitasking controlat
execuia oricrui fir poate fi ntrerupt n cel mai neconvenabil (pentru firul dat) moment i s nceap
execuia unui alt fir. Pentru exemplul nostru momentul nedorit este atunci cnd firul #1 a testat deja
m_pObject, dar nu a reuit s apeleze SomeMethod(). Execuia firului #1 a fost ntrerupt i a nceput
execuia firului #2. Iar firul #2 reuise deja s apeleze destructorul obiectului. Ce se va ntmpla atunci
cnd firului #1 i se va acorda din nou timp de procesor i va fi apelat SomeMethod() al unui obiect deja
inexistent? Greu de presupus.
// Contorul de utilizri
LONG RecursionCount;
HANDLE OwningThread;
HANDLE LockSemaphore;
ULONG_PTR SpinCount;
}
RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
Cmpul LockCount este incrementat cu o unitate la fiecare apelare ::EnterCriticalSection() i
decrementat cu unu la fiecare apel ::LeaveCriticalSection(). Acesta este primul (adesea i unicul)
control pentru testarea seciunii critice. Dac dup incrementare n acest cmp avem 0, aceasta nseamn c
pn la acest moment nu au avut loc apeluri impare ::EnterCriticalSection() din alte fire. n acest caz
datele pzite de aceast seciune critic pot fi utilizate n regim monopol. Adic, dac seciunea critic
este folosit intensiv de un singur fir, atunci ::EnterCriticalSection() se transform practic n +
+LockCount, iar ::LeaveCriticalSection() n--LockCount. Aceasta nseamn, c folosirea a mai multor
mii de seciuni critice ntr-un singur proces nu va conduce la creterea substanial a utilizrii nici a
resurselor de sistem, nici a timpului de procesor. Ca i concluzie: nu se va face economie pe contul
seciunilor critice. Mult totuna nu vom putea economisi.
n cmpul RecursionCount este pstrat numrul de apeluri repetate ::EnterCriticalSection() din unul
i acelai fir. Dac se va apela ::EnterCriticalSection() din unul i acelai fir de mai multe ori, toate
apelurile vor avea succes. Adic urmtorul cod nu se va opri pentru totdeauna n cel de-al doilea apel
::EnterCriticalSection(), ci va merge pn la capt.
// Firul #1
void Proc1()
{
::EnterCriticalSection(&m_lock);
// ...
Proc2()
// ...
::LeaveCriticalSection(&m_lock);
}
// nc Firul #1
void Proc2()
{
::EnterCriticalSection(&m_lock);
// ...
::LeaveCriticalSection(&m_lock);
}
ntr-adevr, seciunile critice sunt destinate s protejeze datele la accesarea din cteva fire. Utilizarea
multipl a uneia i aceeai seciuni critice de un singur fir nu va genera eroare, ceea ce este normal. Trebuie
doar s avem grij ca numrul de apeluri ::EnterCriticalSection() i ::LeaveCriticalSection() s
coincid i totul va fi n regul.
Cmpul OwningThread conine 0 n cazul seciunilor critice libere sau identificatorul unic al firuluiposesor. Acest cmp este testat, dac la apelul ::EnterCriticalSection() cmpul LockCount, dup
incrementarea cu o unitate, a devenit mai mare ca 0. Dac OwningThread coiincide cu identificatorul unic
al firului curent, atunci valoarea lui RecursionCount crete cu o unitate i ::EnterCriticalSection() este
returnat imediat. n caz contrar ::EnterCriticalSection() va atepta pn firul, care posed seciunea critic,
va apela ::LeaveCriticalSection() de un numr necesar de ori. Cmpul LockSemaphore este folosit, dac
este necesar s se atepte pn seciunea critic este eliberat. Dac LockCount este mai mare ca 0 i
OwningThread nu coiincide cu identificatorul unic al firului curent, atunci firul blocat creaz un obiect al
nucleului eveniment i apeleaz ::WaitForSingleObject(LockSemaphore). Firul posesor, dup
decrementarea cmpului RecursionCount, testeaz acest cmp i dac valoarea lui este 0, iar LockCount
este mai mare ca 0, constat c exist minimum un fir n ateptarea momentului cnd LockSemaphore se
va afla n starea sosit. Pentru aceasta firul-posesor apeleaz ::SetEvent() i un fir oarecare (doar unul)
dintre cele blocate este deblocat i are acces la datele critice.
Windows NT/2000 genereaz o excepie, dac ncercarea de a crea un eveniment a euat. Aceasta este just
att pentru funciile ::Enter/LeaveCriticalSection(), ct i pentru
::InitializeCriticalSectionAndSpinCount() cu bitul cel mai semnificativ al parametrului SpinCount setat.
n cazul sistemului de operare WindowsXP creatorii nucleului au procedat un pic altfel. Aici, funciile
::Enter/LeaveCriticalSection() n loc s genereze o excepie, dac nu pot crea un eveniment propriu, vor
folosi un obiect global, unic pentru toi, creat n avans. n aa mod, n caz de deficien catastrofal a
resurselor de sistem, programul sub comanda lui WindowsXP chiopteaz un timp oarecare mai departe.
ntr-adevr, este foarte complicat s scrii programe, care ar fi n stare s continue lucrul dup ce
::EnterCriticalSection() a generat o excepie. De obicei, chiar dac programatorul a prezis o astfel de
situaie, nu se ajunge mai departe de generarea unui mesaj de eroare i stoparea forat a execuiei
programului. Drept rezultat, WindowsXP ignoreaz bitul cel mai semnificativ al cmpului LockCount.
n sfrit, cmpul LockCount. Acest cmp este folosit doar n sistemele multiprocesorale. n sistemele
monoprocesorale, dac seciunea critic este ocupat de un fir oarecare, putem doar comuta comanda la
aceast seciune i trece n ateptarea evenimentului nostru. n sistemele multiprocesorale exist o
alternativ: s executm de cteva ori un ciclu vid, testnd de fiecare dat dac seciunea critic nu a fost
eliberat (ateptare activ). Dac dup un numr de SpinCount ori seciunea critic nu a fost eliberat,
trecem n starea blocat. Aceast modalitate este mult mai eficient dect comutarea la planificatorul
nucleului i napoi. n WindowsNT/2000 bitul cel mai semnificativ al acestui cmp indic dac obiectul
nucleului, variabila handle a cruia se afl n cmpul LockSemaphore, trebuie creat anticipat. Dac
pentru aceasta nu dispunem de resurse de sistem suficiente, sistemul genereaz o excepie i programul i
poate micora posibilitile funcionale sau chiar termina execuia.
return dwRet;
}
VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) elibereaz resursele,
ocupate de seciunea critic. Are urmtorul pseudocod:
VOID RtlDeleteCriticalSection(LPRTL_CRITICAL_SECTION pcs)
{
pcs->DebugInfo = NULL;
pcs->LockCount = -1;
pcs->RecursionCount = 0;
pcs->OwningThread = 0;
if (pcs->LockSemaphore)
{
::CloseHandle(pcs->LockSemaphore);
pcs->LockSemaphore = NULL;
}
}
VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection), BOOL
TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) permit intrarea n seciunea
critic. Dac seciunea critic este ocupat de un alt fir, atunci ::EnterCriticalSection() va atepta pn
aceasta va fi eliberat, iar ::TryEnterCriticalSection() va returna valoarea FALSE. Listingurile din
ntdll.dll sunt:
VOID RtlEnterCriticalSection(LPRTL_CRITICAL_SECTION pcs)
{
if (::InterlockedIncrement(&pcs->LockCount))
{
if (pcs->OwningThread == (HANDLE)::GetCurrentThreadId())
{
pcs->RecursionCount++;
return;
}
RtlpWaitForCriticalSection(pcs);
}
pcs->OwningThread = (HANDLE)::GetCurrentThreadId();
pcs->RecursionCount = 1;
}
BOOL RtlTryEnterCriticalSection(LPRTL_CRITICAL_SECTION pcs)
{
if (-1L == ::InterlockedCompareExchange(&pcs->LockCount, 0, -1))
{
pcs->OwningThread = (HANDLE)::GetCurrentThreadId();
pcs->RecursionCount = 1;
}
else if (pcs->OwningThread == (HANDLE)::GetCurrentThreadId())
{
::InterlockedIncrement(&pcs->LockCount);
pcs->RecursionCount++;
}
else
return FALSE;
return TRUE;
}
VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) elibereaz seciunea critic.
Pseudocodul este urmtorul:
VOID RtlLeaveCriticalSectionDbg(LPRTL_CRITICAL_SECTION pcs)
{
if (--pcs->RecursionCount)
::InterlockedDecrement(&pcs->LockCount);
else if (::InterlockedDecrement(&pcs->LockCount) >= 0)
RtlpUnWaitCriticalSection(pcs);
}
Pentru o utilizare corect a seciunilor critice prezentm mai jos codul claselor seciunilor critice:
class CLock
{
friend class CScopeLock;
CRITICAL_SECTION m_CS;
public:
void Init() { ::InitializeCriticalSection(&m_CS); }
void Term() { ::DeleteCriticalSection(&m_CS); }
void Lock() { ::EnterCriticalSection(&m_CS); }
BOOL TryLock() { return ::TryEnterCriticalSection(&m_CS); }
void Unlock() { ::LeaveCriticalSection(&m_CS); }
};
class CAutoLock : public CLock
{
public:
CAutoLock() { Init(); }
~CAutoLock() { Term(); }
};
class CScopeLock
{
LPCRITICAL_SECTION m_pCS;
public:
CScopeLock(LPCRITICAL_SECTION pCS) : m_pCS(pCS) { Lock(); }
CScopeLock(CLock& lock) : m_pCS(&lock.m_CS) { Lock(); }
~CScopeLock() { Unlock(); }
void Lock() { ::EnterCriticalSection(m_pCS); }
void Unlock() { ::LeaveCriticalSection(m_pCS); }
};
Clasele CLock i CAutoLock sunt utilizate, de obicei, pentru sincronizarea accesrii variabilelor clasei, iar
CScopeLock este destinat, n special, pentru a fi utilizat n proceduri. Compilatorul singur va avea grij
s apeleze ::LeaveCriticalSection() prin intermediul destructorului. Urmeaz un exemplu de folosire a
CScopeLock.
CAutoLock m_lockObject;
CObject *m_pObject;
void Proc1()
{
CScopeLock lock(m_ lockObject); // apelarea lock.Lock();
if (!m_pObject)
return; // apelarea lock.Unlock();
m_pObject->SomeMethod();
// apelarea lock.Unlock();
}
73. Depanarea seciunilor critice
Depanarea seciunilor critice este o ocupaie foarte interesant, dar i dificil. Poi cuta ore i chiar zile n
ir cauza apariiei unei probleme. Erorile, legate de seciunile critice sunt de dou tipuri: de realizare i de
arhitectur. Erorile de realizare pot fi depistate relativ uor i, de regul, sunt generate de utilizarea
incorect (lipsa perechii) a apelurilor ::EnterCriticalSection() i ::LeaveCriticalSection(). Urmeaz un
fragment de cod n care este omis apelul ::EnterCriticalSection().
// n procedur se presupune, c m_lockObject.Lock(); a fost deja apelat
void Pool()
{
for (int i = 0; i < m_vectSinks.size(); i++)
{
m_lockObject.Unlock();
m_vectSinks[i]->DoSomething();
m_lockObject.Lock();
}
}
Apelul ::LeaveCriticalSection() fr ::EnterCriticalSection() va conduce la faptul c chiar
primul apel ::EnterCriticalSection() va stopa execuia firului pentru totdeauna.
n fragmentul de cod de mai jos lipsete apelul ::LeaveCriticalSection():
void Proc()
{
m_lockObject.Lock();
if (!m_pObject)
return;
// ...
m_lockObject.Unlock();
}
n acest exemplu are sens s fie utilizat o clas de tipul CSopeLock. Se mai poate ntmpla ca
::EnterCriticalSection() s fie apelat fr iniializarea seciunii critice cu ajutorul
::InitializeCriticalSection() (de exemplu, n proiectele scrise cu ajutorul lui ATL). n versiunea debug
totul poate lucra foarte bine, iar n versiunea release moare. Aceasta are loc din cauza aa-zisului CRT
(_ATL_MIN_CRT) minimal, care nu apeleaz constructorii obiectelor statice (Q166480,
Q165076). n versiunea ATL 7.0 aceast problem a fost rezolvat. Pot s apar probleme, dac atunci
cnd este folosit o clas de tipul CScopeLock a fost omis identificatorul variabilei, de exemplu,
CScopeLock (m_lock). Compilatorul apeleaz constructorul CScopeLock i imediat distruge acest
obiect fr nume (n conformitate cu standardul!). Adic, imediat dup apelarea metodei Lock() are loc
apelarea metodei Unlock() i sincronizarea nu se produce.
Dintre erorile de arhitectur cea mai frecvent este mbriarea fatal (deadlock, v.5.1.3.3), cnd dou
fire ncearc s acceseze dou i mai multe seciuni critice. Prezentm un exemplu pentru dou fire.
void Proc1()
// Firul #1
{
::EnterCriticalSection(&m_lock1);
// ...
::EnterCriticalSection(&m_lock2);
// ...
::LeaveCriticalSection(&m_lock2);
// ...
::LeaveCriticalSection(&m_lock1);
}
// Firul #2
void Proc2()
{
::EnterCriticalSection(&m_lock2);
// ...
::EnterCriticalSection(&m_lock1);
// ...
::LeaveCriticalSection(&m_lock1);
// ...
::LeaveCriticalSection(&m_lock2);
}
Pot s apar probleme i n cazul copierii unor seciuni critice. Este greu de presupus c codul de mai jos a
fost scris de un programator sntos:
CRITICAL_SECTION sec1;
CRITICAL_SECTION sec2;
// ...
sec1 = sec2;
Din atribuirea de mai sus este dificil s obii foloase. Dar fragmentul urmtor poate fi adesea ntlnit:
struct SData
{
CLock m_lock;
DWORD m_dwSmth;
} m_data;
void Proc1(SData& data)
{
m_data = data;
}
i totul ar fi OK, dac structura SData ar avea on constructor de copiere, de exemplu:
SData(const SData data)
{
CScopeLock lock(data.m_lock);
m_dwSmth = data.m_dwSmth;
}
Presupunem c programatorul a considerat, c este suficient s se ndeplineasc o simpl copiere a
cmpurilor i, n rezultat, variabila m_lock a fost copiat, iar anume n acest moment ea fusese accesat
dintr-un alt fir i valoarea cmpului LockCount este 0. Dup apelul ::LeaveCriticalSection() din acel fir
valoarea cmpului LockCount pentru variabila iniial m_lock a fost decrementat cu o unitate, pentru
variabila copiat rmnnd fr schimbare. Ca rezultat, orice apel ::EnterCriticalSection() nu se va
ntoarce niciodat n acest fir. Va rmne pentru totdeauna n ateptare. Pot exista situaii mult mai
complicate.
Fie un obiect care apeleaz metodele unui alt obiect, obiectele aflndu-se n fire diferite. Apelurile se fac n
mod sincron, adic obiectul #1 transmite execuia firului obiectului #2, apeleaz metoda i se va comuta
napoi la firul su. Execuia firului #1 va fi suspendat pentru toat perioada de execuie a firului obiectului
#2. Presupunem acum, c obiectul #2 apeleaz o metod a obiectului #1 din firul su. Controlul va fi ntors
obiectului #1, dar din firul obiectului #2. Dac obiectul #1 apelase metoda obiectului #2, intrnd ntr-o
seciune critic oarecare, atunci la apelarea metodei obiectului #1 acesta se va bloca pe sine nsui la
intrarea repetat n aceeai seciune critic. Fragmentul de cod care urmeaz vine s exemplifice aceast
situaie.
// Firul #1
void IObject1::Proc1()
{
// Intrm n seciunea critic a obiectului #1
m_lockObject.Lock();
// Apelm metoda obiectului #2, are loc comutarea la firul obiectului #2
m_pObject2->SomeMethod();
// Aici nimerim numai dup ntoarcerea din m_pObject2->SomeMethod()
m_lockObject.Unlock();
}
// Firul #2
void IObject2::SomeMethod()
{
// Apelm metoda obiectului #1 din firul obiectului #2
m_pObject1->Proc2();
}
// Firul #2
void IObject1::Proc2()
{
// ncercm s intrm n seciunea critic a obiectului #1
m_lockObject.Lock();
// Aici nu vom ajunge niciodat
m_lockObject.Unlock();
}
Dac n acest exemplu nu ar fi avut loc comutarea firelor, toate apelurile ar fi avut loc n firul obiectului #1
i nu am fi avut probleme. Exemple de acest gen stau la baza tehnologiei compartimentului COM
(apartments). Nu sunt recomandate apelurile obiectelor, dac au avut loc intrri n seciunile critice.
Primul exemplu din acest subparagraf va fi rescris astfel:
// Firul #1
void Proc1()
{
m_lockObject.Lock();
CComPtr<IObject> pObject(m_pObject); // apelarea pObject->AddRef();
m_lockObject.Unlock();
if (pObject)
pObject->SomeMethod();
}
// Firul #2
void Proc2(IObject *pNewObject)
{
m_lockObject.Lock();
m_pObject = pNewobject;
m_lockObject.Unlock();
}
Accesul la obiect a rmas ca i mai nainte sincronizat, dar apelul SomeMethod() are loc n afara seciunii
critice. Situaia a fost aproape rezolvat. Mai exist o problem mic. S cercetm mai atent Proc2():
void Proc2(IObject *pNewObject)
{
m_lockObject.Lock();
if (m_pObject.p)
m_pObject.p->Release();
m_pObject.p = pNewobject;
if (m_pObject.p)
m_pObject.p->AddRef();
m_lockObject.Unlock();
}
Este evident, c apelurile m_pObject.p->AddRef() i m_pObject.p->Release() au loc n interiorul
seciunii critice. i dac apelarea metodei AddRef() nu genereaz, de obicei probleme, apelarea metodei
Release() poate fi ultimul apel al Release() i obiectul se va autodistruge. n metoda FinalRelease() a
obiectului #2 poate fi orice, de exemplu, eliberarea unor obiecte, care se afl n alte compartimente. Dar
aceasta din nou va conduce la comutarea firelor i poate genera autoblocarea obiectului #1 ca i n
exemplul de mai sus. Pentru a prentmpina aceasta vom folosi aceeai tehnic ca i n Proc1().
// Firul #2
void Proc2(IObject *pNewObject)
{
CComPtr<IObject> pPrevObject;
m_lockObject.Lock();
pPrevObject.Attach(m_pObject.Detach());
m_pObject = pNewobject;
m_lockObject.Unlock();
}
Potenial, acum ultimul apel IObject2::Release() va fi executat dup prsirea seciunii critice. Iar
atribuirea unei valori noi este sincronizat ca i mai nainte cu apelul IObject2::SomeMethod() din firul
#1.
Concluzii:
seciunile critice sunt executate relativ repede i nu cer multe resurse de sistem;
pentru sincronizarea accesrii a mai multor variabile independente este mai bine s fie utilizate
cteva seciuni critice (nu una pentru toate variabilele);
nu este recomandat s fie apelate metode ale unor obiecte strine dintr-o seciune critic.
e) simetrie: prologul i epilogul trebuie s fie identice pentru toate procesele i independente de numrul
lor.
innd cont de aceste specificaii vom construi o soluie de forma:
<iniializare> -- comun tuturor proceselor
<programul procesului pi>:
ciclu
<prolog>
<seciunea critic>
<epilog>
<restul programului>
endciclu
Trebuie s elaborm fragmentele iniializare, prolog i epilog.
75. Excluderea mutual prin ateptare active
nainte de a descrie implementarea excluderii mutuale prin operaii elementare de blocare i deblocare a
proceselor prezentm un mecanism, care permite simularea efectului acestor operaii, meninnd procesele
n stare activ. Un proces n ateptare activ simuleaz blocarea efectund o testare repetat a condiiei de
depire, care poate fi actualizat de alte procese.
76. Algoritmul lui Dekker
Pentru nceput considerm cazul a dou procese p0 i p1. O prim abordare const n reprezentarea condiiei
de ateptare (care este complementar condiiei de depire) printr-o variabil boolean c; vom avea atunci:
c = un proces este n seciunea critic.
Putem propune urmtorul program:
iniializare: c := false;
prolog :
test: if c then
go to test
else
c := true
endif;
<seciunea critic>
epilog :
c := false;
La o analiz mai atent observm (v.3.2.2.3), c dac nu vom face nite ipoteze suplimentare, acest
program nu rezolv problema pus. Iat secvena de intrare n seciunea critic, descompus n instruciuni:
procesul p0
procesul p1
1) test0:
load R0
2)
br (R0=0)
test0
3)
stz
31)
11)
c
21)
test1: load R1
br (R1=0)
stz
test1
(am reprezentat true prin 0, false prin 1, br este operaia de salt condiionat iar stz pune n 0 un
amplasament de memorie). Dac ordinea de execuie este 1, 11, 2, 21, 3, 31 vedem c excluderea mutual
este greit. Problema provine de la faptul c procesul p1 poate consulta c ntre momentul cnd p0 a
consultat c (gsindu-l false) i momentul n care p0 l-a pus pe c n true. Altfel spus, este necesar ca
secvenele de aciuni (1, 2, 3) i (11, 21, 31) s fie executate n mod atomar. Anume acest principiu st la
baza instruciunii Test and Set.
O soluie (algoritmul lui Dekker) poate totui fi construit fr a folosi alte mecanisme de excludere
mutual, n afar de indivizibilitatea accesrii n citire sau actualizarea unui amplasament de memorie.
Prezentm algoritmul pentru dou procese, dei el poate fi extins pentru un numr arbitrar de procese.
Programul folosete trei variabile comune celor dou procese:
var
tur
0..1;
iniializare:
c[0]:=c[1]:=false;
tur:=0;
prolog :
test:
...
epilog :
-- pentru procesul i
c[i]:=false;
Aceast soluie, demonstrarea validitii creia este propus ca exerciiu, prezint un interes pur teoretic. n
practic sunt utilizate instruciuni speciale care asigur indivizibilitatea secvenelor de testare i modificare.
Ateptarea activ poate fi n egal msur utilizat ca mecanism elementar de sincronizare n cazul unor
alte probleme, diferite de excluderea mutual.
Exemplul 4.1.Relum problema exemplului din 3.3.1 (comunicarea a dou procese printr-un segment
comun). Reprezentm printr-o variabil boolean c condiia de ateptare:
c=procesul p a terminat scrierea n segmentul a
Valoarea iniial c=false. Programele se vor scrie astfel:
procesul p
...
scriere(a);
c:=true
procesul q
...
test: if c
then
go to test
endif;
citire(a)
Putem verifica, c soluia este corect: oricare ar fi ordinea de executare a acestor dou procese, deblocarea
lui q este, n cel mai ru caz, retardat cu un ciclu de ateptare activ. Printre altele, aceast proprietate
rmne adevrat dac vom presupune, c mai multe procese q1, q2,,..., qn ateapt terminarea operaiei de
scriere.
Proprietatea, care asigur validitatea schemei de mai sus, const n faptul c modificarea variabilei c este
efectuat de ctre un singur proces. Notm, c aceast schem a fost deja ntlnit n capitolul 2 la
administrarea intrrilor-ieirilor la CDC 6600: un cuplu de procese comunic prin intermediul unei perechi
de indicatori, fiecare dintre care este actualizat de un proces i consultat de altul. Pentru aceasta este
necesar s se poat executa n excludere mutual instruciunile de testare i modificare.
77. Ateptarea activ n sisteme multiprocesorale: Test & Set
Pentru tratarea cu ajutorul ateptrii active a cazului n care mai multe procese actualizeaz i consult
variabile comune, unele maini au o instruciune, care realizeaz ntr-o manier indivizibil consultarea i
actualizarea unui amplasament de memorie. Aceast instruciune, adesea numit Test And Set (tas), este
utilizat n sistemele multiprocesorale (n sistemele monoprocesor mascarea ntreruperilor este suficient
pentru asigurarea excluderii mutuale).
Fie m adresa amplasamentului de memorie considerat, sau lactul, iar R un registru al procesorului. Prin
convenie, dac lactul este n 0, seciunea critic este liber, iar dac este 1 ea este ocupat. Efectul lui
Test And Set este descris mai jos (Mp[m] desemneaz amplasamentul de memorie cu adresa m):
tas R, m : <blocare acces la Mp[m]>
R:=Mp[m]
Mp[m]:=1
<eliberare acces la Mp[m]>
Excluderea mutual prin ateptare activ poate fi programat cu ajutorul urmtoarelor secvene:
iniializare
: stz
prolog : tas
R, m
br(R0)
epilog : stz
-- Mp[m]:=0
$-1
-- test iterat
Fie p un proces care execut P(s) sau V(s), iar q un proces care se afl n firul de ateptare s.f. Algoritmul
primitivelor este urmtorul:
P(s): V(s):
s.c.:=s.c.-1;
s.c.:=s.c.+1;
extragere(q,s.f.);
introducere(p,s.f.)
stare(q):=activ
endif endif
Aceste operaii sunt executate n excludere mutual. Modalitatea de realizare efectiv a semafoarelor i a
primitivelor P i V este descris n 4.3. Operaiile introducere i extragere permit inserarea unui proces ntrun fir de ateptare sau, respectiv, extragerea. Nu facem aici nici un fel de ipoteze despre politica de
gestionare a firului de ateptare: algoritmii de sincronizare trebuie s fie independeni. Politica aleas n
cazul alocrii unui procesor este discutat n 4.3, la fel i detaliile legate de operaiile de blocare i
deblocare.
Exemplul 4.2.Funcionarea unui semafor poate fi comparat cu lucrul unui magazin accesul n care este
admis doar dac la intrare exist couri libere (sau crucioare) n care cumprtorii i duc marfa (intrarea
fr co este interzis). La deschiderea magazinului un anumit numr de couri libere sunt puse la
dispoziia cumprtorilor la intrare. Un cumprtor ia un co liber, intr n magazin i i alege marfa, iar
dac la intrare nu exist un co liber, cumprtorul este obligat s atepte ntr-un fir de ateptare (operaia
P). La ieire cumprtorul pune coul de unde l-a luat (operaia V).
Doar executarea primitivei P poate bloca un proces, acesta va putea fi deblocat doar de un alt proces, care a
executat primitiva V pe acelai semafor. Executarea operaiei V nu este blocant.
79. Semaforul Proprieti
Proprietile principale ale sincronizrii cu ajutorul semafoarelor pot fi deduse din cteva relaii invariante:
relaii verificate iniial i care rmn neschimbate dup executarea primitivelor P i V un numr arbitrar de
ori.
1) Fie, pentru un semafor s:
np(s) numrul total de execuii a operaiei P(s),
nv(s) numrul total de execuii a operaiei V(s).
Are loc relaia:
s.c. = s0 np(s) + nv(s)
(1)
deoarece valoarea iniial a lui s.c. este s0, fiecare operaie P(s) scade din aceast valoare o unitate, iar V(s)
adaug 1.
Aceste operaii, fiind executate n excludere mutual, nici o modificare nu este pierdut.
2) Fie nbloc(s) numrul proceselor blocate n s.f. Are loc relaia:
nbloc(s) = if s.c. 0 then 0 else s.c. endif (2)
care poate fi de asemenea scris
nbloc(s) = max(0, s.c.)
(21)
Relaia (2) iniial este adevrat. Tabelul de mai jos, care indic efectul operaiilor P(s) i V(s) asupra
valorii variabilei nbloc, arat c aceste operaii las relaia (2) invariant.
s.c.<0
s.c.=0
s.c.>0
+1
+1
--
-1
--
--
3) Relaia (2) poate fi scris sub o alt form, care ne va fi util mai departe. Fie nf(s) numrul de treceri
de ctre procese a primitivei P(s), adic suma numrului de executri a lui P(s) fr blocare i a
numrului de deblocri realizate de ctre V(s). Vom avea n acest caz:
nbloc(s) = np(s) nf(s).
Introducnd aceast valoare n (21) obinem:
- nf(s) = max(-np(s), -s.c.-np(s)), sau
nf(s) = min(np(s), s.c.+np(s)).
n fine, utiliznd valoarea lui s.c. din (1), avem:
nf(s) = min(np(s), s.c.+nv(s)). (3)
80. Realizarea excluderii mutuale cu ajutorul semafoarelor
Prezentm o schem, care rezolv problema excluderii mutuale pentru n procese. n cazul n care nu se fac
ipoteze speciale despre gestionarea firului de ateptare, nu se garanteaz lipsa privaiunilor (blocrilor
indefinite).
iniializare
prolog :
P(mutex),
epilog :
V(mutex).
S ne convingem, c soluia prezentat este n conformitate cu specificaiile din 4.1.1. Trebuie s verificm
proprietile a, b i c au loc.
Fie nc numrul de procese, care se afl n seciunea critic la un moment concret de timp. Avem:
nc = nf(mutex) nv(mutex)
(4)
Proprietile n cauz pot fi verificate aplicnd semaforului mutex relaia (3) din 4.1.3.2:
nf(mutex) = min(np(mutex), 1+nv(mutex))
(5)
a) Excluderea mutual
Din (5) avem:
nf(mutex) 1+nv(mutex)
i, utiliznd (4), obinem nc 1: excluderea mutual este asigurat.
b) Absena blocajelor
Presupunem, c nici un proces nu se afl n seciunea critic. Vom avea n acest caz nc = 0, sau
nf(mutex) = nv(mutex) sau nc
nf(mutex) 1+nv(mutex)
procesul q
...
...
P(mutex1)
(11)
...
...
P(mutex2)
(21)
...
...
V(mutex2)
...
V(mutex1)
P(mutex2)
P(mutex1)
V(mutex1)
...
V(mutex2)
Dac traiectoria temporal de execuie a proceselor p i q ncepe cu (1, 11, 2, 21), se va ajunge la o situaie
n care ambele procese sunt blocate pentru un timp infinit, deoarece fiecare dintre procese poate fi deblocat
doar de ctre cellalt. Aceast situaie este numit blocare sau mbriare fatal (eng. deadlock, fr. treinte
fatale).
2). Ateptare infinit n seciunea critic sau impas
Validitatea soluiei propuse se bazeaz pe presupunerea, c toate procesele prsesc seciunea critic n
timp finit. Numai ce am stabilit, c aceast ipotez poate fi infirmat dac seciunile critice se intersecteaz.
Pot fi i alte cauze, care conduc la o ateptare infinit. Astfel, blocarea, incorectitudini sau ciclri infinite
ntr-un proces, care se afl n seciunea critic, pot paraliza toate procesele concurente cu procesul dat. n
cazul unor seciuni critice globale (care prezint interes pentru toi utilizatorii), realizate pentru un sistem
de operare, pot fi propuse urmtoarele soluii:
oricrui proces, care execut o seciune critic global, i se atribuie, pe toat durata acestei execuii, un
statut special, care i confer anumite drepturi particulare: prioritate nalt, protecie contra distrugerii,
etc.
un orologiu de gard este armat la intrarea unui proces n seciunea critic; dac procesul nu prsete
seciunea critic dup un interval de timp predefinit, sistemul de operare foreaz ieirea procesului i
elibereaz astfel seciunea critic. Aceast soluie nu este cea mai bun, or datele globale, manipulate n
seciunea critic, pot s devin incoerente. Este necesar s se ofere posibilitatea restabilirii acestor date
la o stare anterioar, considerat valid, ceea ce implic salvri periodice.
3). Privaiune
Algoritmul excluderii mutuale garanteaz intrarea exact a unui proces n seciunea critic, dac mai multe
procese ncearc acest lucru, cnd seciunea critic este liber. Se poate ntmpla ca un proces particular s
fie reinut pentru un interval de timp nedefinit: acest fenomen se numete privaiune, pe care o vom
rentlni atunci cnd vom studia alocarea resurselor. ntradevr, procesele candidate la intrare, ateapt n
firul de ateptare mutex.f i ordinea lor de deblocare (prin V(mutex)) depinde de politica de gestionare a
acestui fir, despre care nu s-a fcut nici o ipotez.
Pentru cazul cel mai frecvent, cnd firele de ateptare a semafoarelor sunt gestionate conform ordinii prim
sosit prim servit fr prioritate, riscul de privaiune este eliminat
ntradevr, dac presupunem c execuia unei seciuni critice dureaz totdeauna un interval finit de timp,
orice proces, dup o perioad finit de timp, va deveni cel mai vechi n firul su de ateptare.
81. Funcionarea i structura unui nucleu de sincronizare. Strile unui proces. Fire de ateptare
Noiunea de proces i operaiile asociate nu fac, de obicei, parte din setul de baz al calculatorului. Ele vor
fi implementate cu ajutorul unor programe i/sau microprograme, care formeaz nucleul de administrare a
proceselor. n cadrul descrierii unui sistem de operare cu ajutorul mainilor abstracte ierarhice (v. cap.9),
nucleul constituie nivelul cel mai inferior, realizat direct pe maina fizic. Maina abstract, realizat astfel
poate fi numit o main a proceselor, care posed, n afara setului de instruciuni de baz, primitivele care
permit crearea, distrugerea i sincronizarea proceselor. Ca i orice main abstract, maina realizat n
acest mod ascunde unele proprieti ale mainii fizice. Astfel:
noiunea de proces, care este echivalent cu cea de proces virtual, ascunde utilizatorilor nucleului
mecanismul de alocare a procesoarelor fizice. La un nivel superior nivelului nucleului chiar i numrul
procesoarelor nu intervine dect doar asupra performanelor sistemului i nici ntr-un fel asupra
structurii sale logice,
primitivele de sincronizare, realizate de nucleu, ascund mecanismele fizice de comutare a contextului,
de exemplu, cele oferite de ntreruperi.
Structura unui nucleu de sincronizare depinde, printre altele, de specificaiile mainii fizice (gestiunea
ntreruperilor, structura cuvntului de stare, sistem mono- sau multiprocesoral, etc.) i de specificaiile
mainii abstracte care trebuie realizate, ndeosebi de mecanismul de sincronizare ales. Este, totui, posibil
de evideniat cteva caracteristici comune ale acestei structuri, pe care le vom prezenta nainte de a descrie
o realizare concret.
Am considerat pn acuma c un proces se poate afla n dou stri: activ sau blocat. Luarea n consideraie
a alocrii fizice a unui procesor ne impune s descompunem starea activ n dou stri noi. Un proces activ
se numete ales, dac el este n curs de execuie pe un procesor fizic; el se numete eligibil dac nu poate fi
executat din cauza lipsei unui procesor disponibil. Aceast evideniere este legat doar de disponibilitatea
procesorului i nu are vre-un suport logic. Figura 4.1 descrie strile unui proces i tranziiile lui.
Tranziiile 3 i 4 (blocare i deblocare) sunt tranziiile interne, datorate sincronizrii proceselor.
Tranziiile tehnologice 1 i 2 sunt datorate alocrii procesoarelor fizice proceselor. n particular, tranziia
2 se produce atunci cnd algoritmul de alocare ia procesorul de la un proces, care nc mai are nevoie de el.
Aceast operaie este numit retragere (eng. preemption, fr. rquisition) a procesorului.
Administrarea proceselor face apel la fire de ateptare. Astfel, fiecrei cauze distincte de blocare (semafor,
condiie ntr-un monitor, etc.) i se asociaz un fir de ateptare pentru a stabili o ordine a proceselor blocate.
Mai mult, procesele eligibile sunt meninute ntr-un fir special de ateptare, gestionarea cruia permite
implementarea unei politici de alocare a procesoarelor fizice. Dac presupunem, c viitorul proces ales este
totdeauna primul din firul proceselor eligibile, algoritmul de alocare poate fi definit
cu ajutorul algoritmului de inserare n firul proceselor eligibile,
cu ajutorul algoritmului care determin retragerea procesoarelor fizice.
eli
gib
il
(re
ad
y)
(1
)
(2
)
(4
)
ales
(ex
e)
(3
)
blo
cat
(wa
it)
Fig.4.1.
Strile unui
proces
Mulimea programelor, care realizeaz aceti algoritmi se numete planificator (eng. scheduler, fr.
ordonnanceur). Programul, care realizeaz alegerea propriu-zis se numete dispecer (eng. dispatcher, fr.
distributeur). Schema general a firelor de ateptare ale proceselor este prezentat n fig.4.2. Deplasarea
proceselor ntre aceste fire corespunde schimbrii strii.
planifi
cator
fire de
procese
proces
dispe
firul
blocate
ales
cer
proceselor
Fig.4.2. Fire de ateptare ale proceselor,
eligibile
administrate de nucleul
sistemului de operare
prin apelarea unei primitive de administrare a proceselor (creare, distrugere, sincronizare, etc.); aceste
primitive sunt realizate sub form de apel al supervizorului,
printr-o ntrerupere: programele de tratare a ntreruperilor fac parte din nucleu, deoarece ntreruperile
sunt traduse n operaii de sincronizare i sunt invizibile la nivelurile superioare.
n ambele cazuri, mecanismul de intrare n nucleu conine salvarea automat a cuvntului de stare i,
eventual, a registrelor procesorului, care execut apelul supervizorului sau care trateaz ntreruperea. n
dependen de organizarea calculatorului, aceste informaii sunt salvate ntr-un amplasament fix (legat de
nivelul ntreruperii sau de apelul supervizorului) sau ntr-o stiv (ndeosebi n cazul sistemelor
multiprocesorale). Prile contextului, salvate n acest fel, sunt cele ale proceselor alese pentru procesorul
n cauz, n momentul ntreruperii sau apelrii supervizorului.
Programele primitivelor i cele de tratare a ntreruperilor manipuleaz blocurile contextului i firele
proceselor. Pentru asigurarea coerenei informaiilor aceste programe trebuie executate n excludere
mutual. Executarea unui program al nucleului se termin n toate cazurile prin realocarea procesorului sau
procesoarelor, adic prin apelarea dispecerului. Deoarece este posibil ca firul de ateptare a proceselor alese
s fi fost modificat de execuia primitivelor, noul proces ales poate s difere de ultimul proces ales pentru
procesorul ntrerupt.
alocare
proceso
r
apelare
pro
supervizo
ces
r
progr
amul
nucle
perife
ului
lansa
ntrerup
rice,
reFig.4.3. Comunicarea
eri
cu
un
ceasu
nucleu de sincronizare
l
control;
<corpul programului>
alocare_procesor;
Secvena prolog, comun tuturor operaiilor, salveaz contextul procesului, care execut operaia, i asigur
intrarea n seciunea critic. Secvena control verific drepturile procesului apelant de a executa primitiva i
validitatea parametrilor transmii. Detaliile depind de primitiv. Secvena alocare_procesor este programul
dispecerului: ea realizeaz realocarea procesorului i ieirea din seciunea critic.
Diferena ntre sistemele mono- i multiprocesorale se manifest n mod esenial la realizarea excluderii
mutuale i alocrii procesorului (secvenele prolog i alocare_procesor).
Tratarea ntreruperilor de ctre nucleu trebuie s fie coordonat cu mecanismele de sincronizare alese. De
obicei sunt considerate dou scheme de baz:
1) Asocierea unui proces, care trateaz fiecare ntrerupere. Doar acest proces se va afla n ateptarea unei
ntreruperi anume, existnd pentru aceasta o instruciune special.
2) Asocierea unei operaii de deblocare (semnalizare asociat unei condiii, V la un semafor, etc.) la o
ntrerupere.
Problemele de mascare i de prioritate a ntreruperilor sunt, de obicei, tratate asociind prioriti proceselor.
83. Realizarea unui nucleu de sincronizare. Organizarea general intrebarile de mai jos
84. Realizarea unui nucleu de sincronizare. Interfeele
a) Gestionarea proceselor
Procesele pot fi create i distruse n mod dinamic, i sunt organizate ierarhic conform relaiei de legtur
(v.3.5). Un proces este creat cu ajutorul primitivei:
creare(p, context iniial, atribute)
Atributele unui proces conin prioritatea (exprimat printr-un ntreg) i drepturile de a executa anumite
operaii. Contextul iniial specific starea iniial a cuvntului de stare i a registrelor procesorului, i a
spaiului de lucru asociat procesului (stiva, date proprii). Procesul este creat n starea eligibil. Numrul su
p (numele) este returnat ca rezultat (valoarea nil, dac crearea este imposibil). O funcie
determin_numr_propriu permite unui proces s afle numrul su propriu.
Primitivele care urmeaz pot fi aplicate unui proces existent i pot fi executate doar de procesul-printe.
Procedura distrugere poate fi utilizat de ctre un proces pentru a se autodistruge. Deci, distrugere(p) va
distruge toate procesele desemnate de procesul p i toi descendenii acestora.
Procedura suspendare(p) ntrerupe execuia unui proces p, plasndu-l ntr-un fir de ateptare special.
Execuia lui p poate fi reluat doar cu ajutorul primitivei reluare(p). Primitivele suspendare i reluare sunt
introduse din considerente de securitate, n special pentru a permite monitorizarea unui proces de ctre
procesul-printe.
Utilizarea primitivelor creare, distrugere, suspendare i reluare este condiionat de un drept, care
figureaz n atributul drepturi al procesului.
b) Sincronizarea
Procesele sunt sincronizate cu ajutorul monitoarelor. Gestiunea ntreruperilor este integrat n mecanismul
monitoarelor: o ntrerupere este asociat unei condiii. Specificarea primitivelor, care difer un pic de cea
din 3.3, este precizat n 4.3.2. Monitoarele sunt declarate n programele proceselor; un monitor este creat
la compilarea programului, unde el este declarat, i este mai apoi utilizat conform regulilor, definite de
limbajul de programare utilizat (care nu este aici specificat).
85. Realizarea unui nucleu de sincronizare. Structuri i algoritmi
Din momentul crerii sale unui proces i se asociaz un numr fix (process handler), care servete la
desemnarea lui i permite accesarea blocului su de context. Blocul de context conine urmtoarele
cmpuri:
Csp
Reg
: prioritatea procesului,
Drepturi
: drepturile procesului,
Fire, etc.
Suc, etc.
ntoarce numrul (numele) procesului din vrful lui f (nil dac f este vid); nu
ieire(p, f)
Extrage din firul f primul proces, numrul acestuia fiind pus n p (nil dac f este vid).
extragere(p, f)
Extrage din firul f procesul cu numrul p specificat, oricare ar fi elementul n
care acesta se afl; pune n p valoare nil, dac procesul nu exist n firul f.
vid(f)
Funcie boolean cu valoarea adevrat, dac firul f este vid, fals n caz contrar.
Reg[i]
Stare[i]
Drepturi[i]
Prio[i]
.
.
.
blocul
Fig.4.4. Organizarea contextului
unui FA de i
procese
legturi de
nlnuire
context
n n FA
memorie
competiie cu alte procese, care ateapt s intre n monitor, i nu este garantat c va fi imediat ales.
Condiia, care provocase deblocarea, poate fi modificat nainte ca procesul deblocat s-i reia execuia
n monitor. Pentru aceast nou interpretare trebuie s fie modificat forma punerii n ateptare. O
construcie de forma
if continuare_non_posibil then
c.ateptare
endif
devine n acest caz
while continuare_non_posibil do
c.ateptare
endwhile
Dei aceast construcie introduce un risc de privaiune, ea prezint o serie de avantaje de ordin practic. Ea
evit o comutare a contextului, cu preul unei evaluri suplimentare a condiiei. Dar principalul este c ea
permite definirea simpl a unor posibiliti suplimentare utile (deblocare multipl, ntrzieri de control sau
de gard), precizate mai jos. n fine, trebuie s notm, c verificarea validitii monitorului este
simplificat, deoarece condiia de depire (continuare_posibil) este consultat n timpul deblocrii:
procesul care execut semnalizare poate s se mulumeasc cu garantarea unei condiii mai slabe dect
condiia de depire.
2) Deblocare multipl. Problema deblocrii multiple poate fi rezolvat uor introducnd o primitiv nou
c.difuzare_semnal efectul creia se exprim astfel:
while c.non_vid do
c.semnalizare
endwhile
Fiind dat, c toate procesele deblocate vor testa din nou condiia i cer din nou acces la monitor, aceast
primitiv va avea evident efectul ateptat.
3) ntrziere de gard. Din probleme de securitate, n special pentru tratarea blocajelor, poate fi util s se
asocieze o ntrziere de gard condiiei unui monitor. Aceast ntrziere este egal cu durata maxim de
blocare a unui proces ntr-un fir de ateptare asociat condiiei date. La expirarea ntrzierii de gard va
fi efectuat o tratare specificat. Aceast tratare poate consta n simpla deblocare a procesului (care va
testa din nou condiia de depire) sau transferul su ntr-un fir de ateptare special (v.4.3.2.3).
Fie M.c.ntrziere ntrzierea de gard asociat unei condiii c n monitorul M. Se presupune disponibil un
ceas habs, care pune la dispoziie timpul absolut. Trebuie s adugm n programul primitivei c.semnalizare
instruciunea urmtoare:
hdeblocare[p]:=habs+M.c.ntrziere
unde hdeblocare[p] este un cmp nou al blocului de context al procesului p. Un proces, numit gardian,
deblocat la intervale regulate de timp parcurge mulimea contextelor i efectueaz tratamentul specificat
proceselor pentru care hdeblocare[p]>habs.
87. Realizarea unui nucleu de sincronizare. Algoritmi de baz
Programul monitorului trebuie s asigure dou funcii:
eliberare_disp(M):
if M.disp=ocupat then
if vid(M.fir) then
intrare(p, M.fir);
stare[p]:=blocat
else
M.disp:=liber
else
ieire(q, M.fir);
M.disp := ocupat;
intrare(q, f_eligibil);
intrare(p, f_eligibil);
stare[q]:=eligibil
stare[p]:=eligibil
endif
endif
Cele patru secvene se vor scrie utiliznd urmtoarele proceduri:
intrare(M):
prolog;
ieire(M):
prolog;
p:=<proces apelant>;
p:=<proces apelant>;
cerere_disp(M, p);
eliberare_disp(M);
alocare_procesor;
intrare(p, f_eligibil);
alocare_procesor;
c.ateptare:
c.semnalizare:
prolog;
prolog;
p:=<proces apelant>;
p:=<proces apelant>;
intrare(p, M.c.fir);
if non_vid(M.c.fir) then
stare[p]:=blocat;
ieire(q, M.c.fir);
eliberare_disp(M);
cerere_disp(M, p);
alocare_procesor;
cerere_disp(M, q);
eliberare_disp(M)
else
intrare(p, f_eligibil)
endif
alocare_procesor;
S ne amintim, c secvena prolog asigur salvarea contextului i intrarea n seciunea critic, iar secvena
alocare_procesor asigur alocarea procesorului i prsirea seciunii critice (v.4.3.4).
Notm, c n primitiva semnalizare, procesul apelant p i procesul deblocat q sunt introduse (cu ajutorul
primitivei cerere_disp) n firul de ateptare pentru a intra n monitor. Procesul activat prin intermediul
primitivei este primul proces din acest fir. Nu am ncercat s reducem numrul transferurilor ntre fire
pentru a realiza o implementare optimal.
88. Realizarea unui nucleu de sincronizare. Tratarea ntreruperilor
Pentru asigurarea uniformitii mecanismelor de sincronizare fiecrei ntreruperi i se asociaz:
o condiie ntr-un monitor,
un proces ciclic care realizeaz tratarea ntreruperilor, n stare de repaus acest proces este n ateptarea
condiiei.
O condiie poate fi asociat unui singur nivel de ntrerupere. Sosirea unei ntreruperi provoac executarea
funciei semnalizare pentru condiia asociat. Prioritatea relativ a ntreruperilor este tradus n prioritatea
proceselor, care trateaz ntreruperile.
Mecanismul descris mai sus nu este absolut perfect. De exemplu, excluderea procedurilor monitorului nu
poate fi aplicat ntreruperilor. Se poate ntmpla ca o ntrerupere s fie cerut atunci cnd procesul, care
trateaz ntreruperile, este nc activ, din care cauz ntreruperea va fi pierdut. Evitarea acestui fenomen se
va face cu ajutorul unui indicator boolean, care memorizeaz sosirea unei ntreruperi. Vom avea:
<proces de prelucrare a ntreruperii>
ciclu
test
if nonM.c.ntr_sosit then
c.ateptare;
go to test
endif;
<tratarea ntreruperii>
endciclu
<sosirea unei ntreruperi asociate lui M.c>
M.c.ntr_sosit := true;
c.semnalizare;
Principiul de tratare a erorilor const n blocarea procesului care a provocat eroarea i expedierea unui
mesaj procesului printe, care va putea lua msurile necesare (corectarea erorii i relansarea sau distrugerea
procesului, care a generat eroare). Pentru aceasta este folosit un fir special f_eroare (n conformitate cu
organizarea sistemului, poate fi prevzut un fir unic sau un fir pentru fiecare utilizator, pentru fiecare
subsistem, etc.).
Presupunem c o eroare care are loc n cursul execuiei unui proces provoac o deviere, tratarea creia se
va scrie astfel:
prolog;
p:=<proces apelant>;
intrare(p, f_eroare);
<tratare specific>;
stare[p]:=suspendat;
alocare_procesor;
Am definit o stare nou (suspendat), care se aplic unui proces activitatea cruia a fost ntrerupt de un
eveniment, considerat anormal (eroare de execuie sau aciunea primitivei suspendare, v.4.3.3).
Nu detaliem aici <tratare specific>, care trebuie s fie specificat de ctre procesul printe la momentul
crerii procesului descendent. Acest program conine, evident, codul de diagnosticare (identitatea
procesului generator de eroare, natura erorii), care trebuie transmis procesului printe ntr-un mod special,
conform gradului de urgen (actualizarea unui indicator, deblocare, etc.).
90. Operaii asupra proceselor. Crearea i distrugerea proceselor. Suspendarea i reluarea
Problema principal, condiionat de gestiunea dinamic a proceselor, este alocarea contextelor i numelor
proceselor. Pentru aceasta sunt utilizate dou metode principale:
pentru blocurile contextelor sunt rezervate un numr fix de amplasamente; amplasamentele neutilizate
sunt determinate de o valoare special (nil) a cmpului stare al lor; fiecare bloc este desemnat printr-un
numr, care este numrul utilizat pentru desemnarea procesului asociat;
amplasamentele rezervate blocurilor de context sunt alocate dinamic n memorie; numerele sunt alocate
proceselor de asemenea n mod dinamic i un tabel de coresponden, asociaz numrului fiecrui
proces adresa n memorie a blocului su de context.
n ambele cazuri vom presupune disponibil o procedur alocare_context(p), care realizeaz alocarea
contextului (blocul de context i spaiul de lucru) i ntoarce ca rezultat un numr p al procesului (nil, dac
crearea este imposibil, de exemplu, din cauza lipsei de spaiu suficient n memorie). Metodele de alocare a
spaiului de lucru nu sunt precizate aici. Numrul procesului creat este ntors drept rezultat al primitivei:
creare(p, context iniial):
prolog;
control;
-- verificarea drepturilor
alocare_context(p);
if p nil then
iniializare_context(i);
intrare(p, f_eligibil)
endif;
intrare(proces apelant, f_eligibil);
alocare_procesor;
Contextul iniial este specificat de ctre procesul creator: el trebuie s defineasc valoarea iniial a
registrelor i a cuvntului de stare a procesului creat, starea iniial a spaiului de lucru, atributele, cum ar fi
prioritatea i drepturile. Unele cmpuri ale cuvntului de stare sunt predefinite i nu pot fi modificate
(modul, mascarea ntreruperilor, etc.). Pentru elementele legate de protecie (drepturile de acces), procesul
creat nu poate avea drepturi superioare drepturilor procesului creator; n caz contrar atributele de protecie
sunt declarate defecte.
Distrugerea unui proces trebuie s implice eliberarea resurselor, care i fuseser alocate. Printre aceste
resurse, doar numele i contextul sunt gestionate direct de nucleu; celelalte resurse, cum ar fi fiierele, sunt
preluate de mecanisme specifice.
Distrugerea unui proces, care se afl n seciunea critic poate conduce la o blocare. Seciunile critice ale
monitoarelor sunt gestionate direct de nucleu. Este posibil s se asocieze unui proces numrul
dispozitivului de blocare, care se afl n posesia procesului dat (el poate fi angajat n mai multe apeluri
incorporate), i s difereniem distrugerea procesului pn cnd valoarea acestui numr nu va fi 0. O alt
soluie const n examinarea periodic a fiecrui dispozitiv de blocare i s eliberm dispozitivul de
blocare, dac procesul care l posed a fost distrus.
Principiul primitivei distrugere este dat n schema de mai jos:
distrugere (p):
prolog;
control;
-- verificarea drepturilor
eliberare_context(p);
intrare(proces apelant, f_eligibil);
alocare_procesor;
Procedura eliberare_context trebuie s asigure eliberarea resurselor ocupate de procesul distrus i de
descendenii acestuia:
eliberare_context(p):
list:=<lista firelor procesului p>;
restituire_bloc_context(p);
restituire_memorie(p);
for q list do
eliberare_context(q)
endfor;
Primitiva suspendare
Primitiva suspendare permite procesului-printe s controleze activitatea unui proces descendent,
ntrerupnd n mod forat execuia acestuia. O utilizare curent este suspendarea unui proces, angajat ntr-o
bucl infinit. Procesul ntrerupt n acest mod este transferat ntr-un fir de ateptare special, care poate fi
firul f_eroare, utilizat pentru devieri.
Efectul primitivei suspendare poate fi ca i al unei devieri i programul de tratare poate fi analogic.
Suspendarea unui proces pune o problem analogic celei de distrugere, dac procesul se afl n seciunea
critic ntr-un monitor.
suspendare(p):
prolog;
control;
< tratare seciune critic>;
f:=<fir care conine p>;
extragere(p, f);
intrare(p, f_eroare);
stare[p]:=suspendat;
intrare(proces apelant, f_eligibil);
alocare_procesor;
Primitiva reluare permite unui proces s deblocheze un fir suspendat, dup modificarea eventual a
contextului su.
reluare(p):
prolog;
control;
extragere(p, f_eroare);
stare[p]:=eligibil;
intrare(proces apelant, f_eligibil);
intrare(p, f_eligibil);
alocare_procesor;
91. Excluderea mutual i alocarea procesorului intrebarile de mai jos
92. Realizarea pentru cazul monoprocesor
n acest caz excluderea mutual este realizat prin mascarea ntreruperilor. Pentru aceasta trebuie pregtit
masca ntreruperii n cuvntul de stare, care ar specifica programele asociate primitivelor de tratare a
ntreruperilor. Dac notm prin proces_ales o variabil global, care conine numrul procesului ales, iar
prin salv_csp locaiunea n care a fost salvat cuvntul de stare a procesorului la apelarea supervizorului sau
la ntrerupere, prologul va fi de forma:
prolog:
<mascarea ntreruperilor> -- masca n cuvntul de stare
csp[proces_ales] := salv_csp;
salv_registre(Reg[proc_al]);
Programul dispecerului, care de asemenea realizeaz ieirea din seciunea critic, are grij s aloce
procesorul primului proces din firul de procese eligibile. Pentru simplificarea manipulrii acestui fir este
binevenit s fie introdus aici un proces special cu prioritate joas, care rmne tot timpul n coada firului i
nu poate fi blocat. Acest proces, care poate fi ales doar atunci cnd el este unicul eligibil, execut o
activitate de fond, care nu este urgent sau o simpl bucl de ateptare. El garanteaz, deci, c firul
proceselor eligibile nu este niciodat vid.
f_elig
ibil
Csp
Reg
Prio
p =6
1 c.fii
p
2
p
3
er
f_elig
ibil
c.fiie
r
p
5
Cuvnt de
stare
Registre
proc_
al
p
5
p
1
p
4
p
6
p
2
Csp
Reg
2
Procesor
p
4
(a) nceputul
executrii
c.ateptare
Cuvnt de
stare
Registre
proc_
al
Procesor
p
3
(b) sfritul
executrii
c.ateptare
1
p
6Fig.4.5. Alocarea
procesorului
ncrcare_registre(Reg[proc_al]);
ncrcare_csp(csp[proces_ales]);
Figura 4.5 ilustreaz principiul de funcionare a nucleului, exemplificnd efectul global al unei realocri a
procesorului dup blocarea procesului ales.
93. Realizarea pentru cazul unui sistem multiprocesoral
Descrierea, care urmeaz este inspirat din [13]. Vom specifica mai nti organizarea fizic a sistemului.
Avem n procesoare identice, care acceseaz o memorie comun. Fiecare procesor, desemnat printr-un
numr (de la 0 la n-1), i cunoate numrul propriu. Regimului de funcionare multiprocesor i sunt
specifice dou instruciuni:
Test and Set(R, m)
ntrerupere(k) :
-- procesorul k
<mascare ntreruperi>;
Csp[proc_al[k]]:=top(stiv_csp);
Reg[proc_al[k]]:=top(stiv_reg);
test:
-- ateptare activ
endif
Dispecerul va asigura ca cele n procese alese s fie la orice moment de timp cu prioritatea cea mai nalt
printre procesele eligibile. Deoarece executarea primitivei curente poate modifica firul proceselor eligibile,
prioritatea primului proces eligibil este comparat cu prioritatea procesului ales pentru procesorul kmin.
Dac aceasta este superioar procesorul dat este retras cu ajutorul instruciunii ntrerupere.
alocare_procesor:
ieire(proces_ales[k], f_eligibil);
pr1:=Prio[primul(f_eligibil)];
pr2:=Prio[proc_al[kmin]];
if Prio[proc_al[k]] < pr2 then
kmin:=k
endif;
disp_de_blocare:=0; -- terminarea seciunii critice
if pr1 > pr2 then
ntrerupere(kmin)
-- retragere
endif;
ncrcare_registre(Reg[proc_al[k]];
ncrcare_csp(Csp[proc_al[k]];
-- demascarea ntreruperilor
Firele sunt realizate n biblioteca standard de susinere a programelor cu mai multe fire ca i procesele,
generate cu indicatorul Clone_VM, i, din punctul de vedere al nucleului sistemului, nu se deosebesc de
alte procese. ns n unele biblioteci de alternativ pot exista diferene.
Mai exist fire, numite handicapate, generate de funcia kernel_thread pentru necesiti interne ale
sistemului. Acestea nu au parametri pentru linia de comand, de obicei nu au fiiere deschise, etc. Deoarece
aceste fire (procese) de asemenea figureaz n lista lucrrilor, adesea n literatur poate fi ntlnit noiunea
de proces propriu-zis, creat din spaiul utilizatorului (userspace), i noiunea de lucrare, prin aceasta
nelegndu-se toate procesele, inclusiv procesele interne ale nucleului.
Procesele sunt create prin utilizarea funciilor din familia exec ale bibliotecii Linux standard: execl,
execlp, execle, execv, execve, execvp. Dei formatul de apelare este diferit, n ultim instan execut
acelai lucru: nlocuiesc codul din procesul curent cu codul, care se afl n fiierul indicat. Fiierul poate fi
un fiier binar executabil Linux, un script al interpretorului limbajului de comand, un fiier binar de un alt
format (de exemplu, o clas java, un fiier executabil DOS). n ultimul caz modalitatea de prelucrare va fi
determinat de modulul de adaptare a nucleului binfmt_misc. Din aceast cauz, operaia de lansare a unui
program, care n DOS i Windows formeaz un tot ntreg, n Linux (i n Unix, n general) este mprit n
dou: mai nti are loc lansarea propriu-zis, iar apoi se va determina care program va fi executat. Are oare
aceasta sens i care sunt cheltuielile suplimentare? Doar crearea copiei unui proces presupune copierea
unui volum semnificativ de informaii!
n mod sigur putem afirma c are sens aceast abordare. Foarte frecvent un program trebuie s
ndeplineasc unele aciuni nainte de nceperea propriu-zis a execuiei lui. De exemplu, lansm dou
programe, care-i transmit reciproc date prin intermediul unui canal fr nume. Astfel de canale sunt create
prin apelarea de sistem pipe, care returneaz o pereche de descriptori de fiiere de care pot fi legate, de
exemplu, fluxul standard de intrare (stdin) al unui program i de ieire (stdout) al celuilalt program.
Aceasta este posibil deoarece mai nti sunt create procesele, apoi vor fi executate manipulrile necesare cu
descriptorii fiierelor i doar dup toate acestea este apelat funcia exec.
Aceleai rezultate pot fi obinute n Windows NT ntr-un singur pas, dar ntr-un mod mult mai complicat.
Ct despre cheltuielile suplimentare ele sunt n majoritatea cazurilor minime, deoarece dac este creat
copia unui proces datele proprii ale acestuia nu sunt fizic copiate. i aceasta din cauza c este utilizat
procedeul copy-on-write: paginile datelor ambelor procese sunt marcate ntr-un anumit mod i doar atunci
cnd un proces va ncerca s modifice coninutul uneia din paginile sale aceasta va fi duplicat.
Primul proces este lansat n sistem la iniializarea nucleului. Fragmentul de cod de mai jos este partea de
ncheiere a procedurii de iniializare a nucleului sistemului de operare Linux:
if (execute_command)
execve(execute_command,argv_init, envp_init);
execve("/sbin/init",argv_init,envp_init);
execve("/etc/init",argv_init,envp_init);
execve("/bin/init",argv_init,envp_init);
execve("/bin/sh",argv_init,envp_init);
panic("No init found. Try passing init= option to kernel.");}
Este fcut ncercarea de comutare a procesului la fiierul, indicat n linia de comand a nucleului, apoi la
fiierele
/sbin/init, /etc/init, /bin/init i, n sfrit, la fiierele din /bin/sh.
Distrugerea proceselor
La terminarea execuieia unui proces (normal, forat sau accidental), el este distrus elibernd toate
resursele, care fusese alocate anterior. Dac procesul printe se termin naintea procesului descendent,
ultimul devine orfan (orphaned process). Toi orfanii sunt nfiai n mod automat de programul init,
executat de procesul cu numrul 1, care duce evidena terminrii execuiei lor.
Dac a fost terminat deja execuia procesului descendent, iar procesul printe nu este gata s recepioneze
de la sistem semnalul despre acest eveniment, descendentul nu dispare total, ci este transformat n Zombie;
n cmpul Stat aceste procese sunt notate cu litera Z. Procesele Zombi nu cer timp de procesor, dar n
tabelul proceselor este pstrat linia lor i structurile respective ale nucleului nu sunt eliberate. Dup
terminarea execuiei procesului printe, procesul Zombi orfan devine pentru o perioad scurt de timp
descendentul lui init, ca mai apoi s moar definitiv.
Un process poate s cad n hibernare, fr a putea fi scos din aceast stare: n cmpul Stat acest
eveniment se va nota prin litera D. Procesele aflate n hibernare nu reacioneaz la cererile de sistem i pot
fi distruse doar prin rencrcarea sistemului.
Demoni n Linux
Demon (daemon) n Linux este numit procesul predestinat s lucreze n regim de fond fr terminal i
care execut anumite operaii pentru alte procese (nu obligator pe calculatorul Dumneavoastr). De obicei,
demonii i ndeplinesc n linite lucrul i ne amintim de ei doar n cazul unor situaii ieite din comun:
spaiu insuficient demonul singur informnd utilizatorul despre aceasta, sau refuz s lucreze i suntei
ntrebat de ef cnd se vor termina problemele cu imprimant .
Pentru multe calculatoare demonii, care servesc procesele altor calculatoare, sunt rar utilizai din care cauz
nu trebuiesc pstrai constant n memorie cu cheltuieli neraionale ale resurselor sistemului. Pentru
coordonarea lucrului acestora a fost creat un superdemon inetd (Internet daemon).
n fiierul de configurare inetd (/etc/inetd.conf) este indicat care demon acceseaz un serviciu anume de
Internet. De obicei, cu ajutorul lui inetd sunt apelate programele pop3d, imap4d, ftpd, telnetd (exerciiu determinai serviciul pus la dispoziie), etc. Aceste programe nu sunt n mod constant active, n rezultat, ele
nu pot fi considerate demoni n adevratul sens al cuvntului, dar, deoarece ele sunt create de un demon
adevrat, sunt numite demoni.
Pentru obinerea informaiilor despre procese, vizualizate de programele ps i top, Linux-ul utilizeaz
un sistem special de fiiere, numit procfs. n majoritatea distributivelor el este iniializat la lansarea
sistemului de operare cu titlul de catalog /proc. Datele despre procesul cu numrul 1 (de obicei /sbin/init)
se afl n subcatalogul /proc/1, despre procesul cu numrul 182 - n /proc/182, etc. Toate fiierele,
deschise de un proces, sunt reprezentate sub forma unor referine simbolice n catalogul /proc/<pid>/fd, iar
referina la catalogul rdcin este pstrat ca /proc/<pid>/root.
Sistemului de gestiune a fiierelor procfs i sunt asociate i alte funcii. De exemplu, cu ajutorul comenzii
echo 100000>/proc/sys/fs/file-max un superuser poate indica, c se permite deschiderea unui numr de
pn la 100000 de fiiere, iar comanda echo 0>/proc/sys/kernel/cap-bound va retrage proceselor din
sistem toate drepturile suplimentare, adic va priva sistemul de noiunea superuser.
Informaii utile pune la dispoziie programul lsof. Acesta returneaz lista tuturor fiierelor, utilizate la
momentul curent de ctre procese, inclusiv cataloagele folosite de ctre unele procese n calitate de catalog
curent sau catalog rdcin, bibliotecile dinamice, ncrcate n memorie, etc.