Sunteți pe pagina 1din 13

Lucrarea 6

Fire de Execuie i Mecanisme de Sincronizare n


Windows
1
Fiecare proces are la crearea sa un singur fir de execuie i pn nu demult acest lucru
prea suficient. Pentru cazurile n care un singur de fir de execuie nu mai este de ajuns
avem n cazul sistemelor de operare mai multe soluii.
Prima soluie este oferit de utilizarea funcie:
H!"#$ %reate&'read(
#P)$%*+,&-.&&+,/*&$) lp&'readttri0utes1
),2$.& d3)tac4)ize1
#P&H+$".)&+&.+5*&,!$ lp)tartddress1
#P65," lpParameter1
"75+" d3%reationFlags1
#P"75+" lp&'read,d
89
Parametrii funciei au urmtoarea utilizare:
lp&'readttri0utes :in
;
< = este un pointer la o structur
)$%*+,&-.&&+,/*&$) care determin dac descriptorul ntors de apel poate
fi motenit de procesele copii. "ac acest parametru este !*## atunci
descriptorul nu va fi motenit.
d3)tac4)ize :in< = reprezint dimensiunea iniial a stivei. "ac acest parametru
are valoarea > atunci noul fir de execuie va utiliza o stiv avnd dimensiunea
implicit a executa0ilului.
lp)tartddress :in< = este un pointer la funcia care va fi executat de ctre fir i
reprezint adresa de start a acestuia. !u are o valoare implicit.
lpParameter :in< = pointer la o varia0il care va fi transmis firului.
d3%reationFlags :in< = fanioane care controleaz modul de creare al unui fir.
"ac firul este creat avnd specificat fanionul %+$&$.)*)P$!"$"
specificat1 firul va fi creat n starea suspendat i nu va rula pn la apelul funciei
+esume&'read. "ac aceast valoare este > atunci firul va fi rulat imediat dup
creare.
lp&'read,d :out< = este un pointer la o varia0il n care va fi memorat
identificatorul firului1 cu condiia ca acest parametru s fie diferit de !*##. ?n
7indo3s @eABCABD acest parametru nu poate fi !*##.
E
?n afara cazului n care este specificat altfel1 termenul F7indo3sF se refer la toate sistemele de operare
@icrosoft de la 7indo3s BD pn la 7indo3s GP.
;
Parametru de intrare.
?n caz de eec funcia ntoarce !*##1 altfel va ntoarce descriptorul firului. ?n @)"!
#i0rarH putei gsi urmtorul exemplu de utilizare a funciei:
Iinclude J3indo3s.'K
Iinclude Jconio.'K
"75+" 7,!P, &'readFunc( #P65," lpParam 8
L
c'ar sz@sg:C><9
3sprintf( sz@sg1 FParameter M Nd.F1 O("75+"O8lpParam 89
@essage/ox( !*##1 sz@sg1 F&'readFuncF1 @/.5P 89
return >9
Q

void main( void 8
L
"75+" d3&'read,d1 d3&'rdParam M E9
H!"#$ '&'read9
c'ar sz@sg:C><9
'&'read M %reate&'read(
!*##1 AA default securitH attri0utes
>1 AA use default stac4 size
&'readFunc1 AA t'read function
Rd3&'rdParam1 AA argument to t'read function
>1 AA use default creation flags
Rd3&'read,d89 AA returns t'e t'read identifier

AA %'ec4 t'e return value for success.

if ('&'read MM !*##8
L
3sprintf( sz@sg1 F%reate&'read failed.F 89
@essage/ox( !*##1 sz@sg1 FmainF1 @/.5P 89
Q
else
L
.getc'(89
%loseHandle( '&'read 89
Q
Q
Firul principal transmite valoarea E noului fir1 care o afieaz. &erminarea unui fir nu
presupune i tergerea o0iectului asociat firului de ctre sistemul de operare. *n o0iect
t'read este ters atunci cnd i ultimul descriptor (H!"#$8 ctre fir este nc'is1 acest
lucru realiznduSl apelul:
%loseHandle( '&'read 89
?n cazul n care dorii s folosii funcii din 0i0liotecile % statice1 utilizarea %reate&'read
nu este prea indicat deoarece duce la mici pierderi de memorie la terminarea fiecrui fir.
?n acest caz este recomandat utilizarea celei deSa doua metode1 oferit de funciile:
uintptr.t .0egint'read(
void( ..cdecl Ostart.address 8( void O 81
unsigned stac4.size1
void Oarglist
89
uintptr.t .0egint'readex(
void OsecuritH1
unsigned stac4.size1
unsigned ( ..stdcall Ostart.address 8( void O 81
void Oarglist1
unsigned initflag1
unsigned Ot'rdaddr
89
Parametrii:
start.address = adresa de nceput a funciei cu care ncepe execuia noului fir.
stac4.size = dimensiunea stivei pe care o va folosi noul fir. "ac acest parametru
este > atunci va fi folosit aceeai dimensiune ca n cazul firului principal.
arglist = un pointer la zona de memorie care conine varia0ilele care tre0uie
transmise firului sau !*##.
securitH = pointer la o structur )$%*+,&-.&&+,/*&$) care determin dac
descriptorul ntors de apel poate fi motenit de procesele copii. "ac este !*##
atunci descriptorul nu va fi motenit. ?n 7indo3s BD acest parametru tre0uie s
fie !*##.
initflag = )tarea iniial a noului fir1 %+$&$.)*)P$!"$" dac dorii ca firul
s fie creat n starea suspendat1 caz n care tre0uie rulat funcia +esume&'read1
sau > pentru ca firul s fie rulat c'iar de la creare.
t'rdaddr = pointer la o varia0il pe T; de 0ii n care va fi memorat identificatorul
firului.
?n caz de succes am0ele funcii ntorc un descriptor pentru noul fir creat. ?n caz de eroare
.0egint'read ntoarce =E#1 iar cealalt funcie ntoarce >.
tunci cnd un fir se termin se apeleaz automat .endt'read1 respectiv .endt'readex.
pelul endt'read nc'ide automat descriptorul asociat cu firul1 lucru pe care nuSl face
.endt'readex.
tunci cnd dorii s compilai un program care folosete aceste funcii va tre0ui s
folosii o 0i0lioteca multifir. 5 cale prin care putei realiza acest lucru este dat de
modificarea setrii F*se runStime li0rarHF
T
astfel nct s conin @ultit'readed n nume.
Iinclude Jstdio.'K
Iinclude Jprocess.'K
Iinclude J3indo3s.'K
volatile running9
void fir(voidO numar89
void main(8L
running M >9
for(int iME9 iJMU9 iVV8L
.0egint'read(fir1 >1 Ri89
)leep(E>>>#89
Q
3'ile(running89
Q
void fir( voidO numar8L
runningVV9
printf(Ffirul numarul Nd. +uleaza: NdWnF1O(intO8numar1 running89
)leep(U>>>#89
runningSS9
printf(Fmurit una1 mai sunt: NdWnF1 running89
Q
$xemplul de mai sus are mai multe 0ugSuri1 unul dintre ele fiind folosirea a0uziv a
calificatorului volatile. 50iectele declarate ca volatile nu sunt folosite n optimizri de
ctre compilator deoarece valoarea lor poate fi modificat de ctre altcineva. )istemul va
citi de fiecare dat valoarea curent a o0iectului volatil c'iar dac aceasta se gsea deja
ntrSun registru i valoarea volatil va fi scris imediat dup asignare. "ar nimeni nu
garanteaz c operaiile sunt atomice. ,at cum arat incrementarea valorii running n
asam0lare:
T
ProjectSK)ettings sau ltVFX dup care la ru0rica %A%VV se selecteaz din com0oSul %ategorH valoarea
%ode Yeneration.
mov eax1:running (>>U;dTf>8<
add eax1E
mov :running (>>U;dTf>8<1eax
cest modificator este potrivit numai pentru instruciuni n care varia0ila respectiv este
numai folosit sau numai atri0uit.
*n alt 0ug1 i nu singurul1 coninut de exemplul anterior este dat de faptul c folosete
ateptarea continu pentru sincronizare. "in fericire1 n 7indo3s avem o mare varietate
de mecanisme de sincronizare. ?n continuare1 o s fie prezentate doar trei dintre ele:
evenimente1 mutexuri i semafoare.
Evenimente, Mutex-uri i Semafoare
*n o0iect eveniment poate avea doar dou stri: semnalizat sau nesemnalizat. $ste util n
cazul n care dorii s transmitei unui fir un anumit semnal care sSi indice c un anumit
eveniment a avut loc1 avnd avantajul fa de varia0ilele condiie c pierderea
respectivului semnal este mult mai greu de o0inut printrSo programare defectuoas.
%rearea unui o0iect eveniment se face cu ajutorul funciei
U
:
H!"#$ %reate$vent(
#P)$%*+,&-.&&+,/*&$) lp$ventttri0utes1
/55# 0@anual+eset1
/55# 0,nitial)tate1
#P%&)&+ lp!ame
89
lp$ventttri0utes = reprezint un pointer la o structur
)$%*+,&-.&&+,/*&$) n funcie de care se sta0ilete dac descriptorul
ntors poate fi motenit de un proces copil. "ac acest parametru este !*##1
atunci el nu va fi motenit.
0@anual+eset = dac acest parametru este &+*$ atunci evenimentul este resetat
manual1 aceasta nsemnnd c tre0uie folosit funcia +eset$vent. "ac acest
parametru este F#)$ atunci evenimentul este resetat automat la eli0erarea unui
singur fir care atepta ca respectivul eveniment s devin semnalizat.
D
0,nitial)tate = reprezint starea iniial: &+*$ M semnalizat9 F#)$ M
nesemnalizat.
lp!ame = un pointer la un string care specific numele pe care l va avea
evenimentul sau !*## dac dorii s nu ai0 un nume. "ac exist un alt o0iect
cu acelai nume de alt tip apelul eueaz. "ac exist evenimentul cu acest nume1
creat de un alt fir1 funcia necesit dreptul de acces $6$!&.##.%%$)).
%omparaia numelor este fcut firete innduSse cont de tipul caracterelor.
U
&oate funciile descrise n continuare necesit includerea F7indo3s.'F i 0i0lioteca PerenelT;.li0.
D
dic semnalizarea duce la eli0erarea numai a unui singur fir1 indiferent de cte ateapt.
?n caz de succes funcia ntoarce un descriptor pentru eveniment. ?n caz de eec ntoarce
!*##1 iar dac evenimentul este deja creat ntoarce descriptorul respectivului eveniment
i GetLastError va ntoarce $++5+.#+$"-.$G,)&).
Pentru a o0ine un descriptor pentru un eveniment deja creat de un alt fir dintrSun alt
proces1 avem funcia:s
H!"#$ 5pen$vent(
"75+" d3"esiredccess1
/55# 0,n'eritHandle1
#P%&)&+ lp!ame
89
d3"esiredccess = specific modul de acces la eveniment
Z
. pelul eueaz dac
accesul cerut nu este permis.
0,n'eritHandle = dac este &+*$ atunci poate fi motenit1 altfel nu.
lp!ame = numele evenimentului.
?n caz de succes funcia ntoarce un descriptor al evenimentului1 altfel ntoarce !*##.
Pentru a semnaliza un o0iect se folosete funcia )et$vent:
/55# )et$vent(
H!"#$ '$vent
89
'$vent = descriptorul evenimentului1 care tre0uie s ai0 setat dreptul
$6$!&.@5",F-.)&&$.
Funcia ntoarce n caz de succes o valoare diferit de zero sau zero n caz de eec.
"ac evenimentul este reseta0il manual1 din cnd n cnd este poate util sSi sc'im0ai
starea n nesemnalizat1 folosind funcia +eset$vent:
/55# +eset$vent(
H!"#$ '$vent
89
'$vent = descriptorul evenimentului1 care tre0uie s ai0 setat dreptul
$6$!&.@5",F-.)&&$.
Funcia ntoarce n caz de succes o valoare diferit de zero sau zero n caz de eec.
Pentru a atepta unul sau mai multe evenimente se vor folosi funciile de ateptare.
Pentru a crea un o0iect mutex avem funcia:
H!"#$ %reate@utex(
#P)$%*+,&-.&&+,/*&$) lp@utexttri0utes1
/55# 0,nitial53ner1
Z
%onsultai F)Hnc'ronization 50ject )ecuritH and ccess +ig'tsF din @)"! pentru detalii.
#P%&)&+ lp!ame
89
lp@utexttri0utes = pointer la o structur )$%*+,&-.&&+,/*&$) care
specific dac descriptorul poate fi motenit. "ac este !*## atunci descriptorul
nu poate fi motenit.
0,nitial53ner = dac acest parametru este &+*$ i firul apelant este cel care a
creat mutexul atunci firul apelant devine proprietarul mutexului. ltfel1 nu.
lp!ame = numele mutexului. "ac exist un mutex cu acelai nume atunci funcia
va cere @*&$G.##.%%$)). "ac exist un alt tip de o0iect cu acelai nume
atunci funcia eueaz.
?n caz de succes funcia ntoarce un descriptor pentru mutex. ?n caz de eec ntoarce
!*##1 iar dac mutexul este deja creat ntoarce descriptorul respectivului mutex i
GetLastError va ntoarce $++5+.#+$"-.$G,)&).
Pentru a o0ine un descriptor pentru un mutex deja creat de un alt fir dintrSun alt proces1
avem funcia:s
H!"#$ 5pen@utex(
"75+" d3"esiredccess1
/55# 0,n'eritHandle1
#P%&)&+ lp!ame
89
d3"esiredccess = specific modul de acces la mutex
X
. pelul eueaz dac
accesul cerut nu este permis.
0,n'eritHandle = dac este &+*$ atunci poate fi motenit1 altfel nu.
lp!ame = numele mutexului.
?n caz de succes funcia ntoarce un descriptor al mutexului1 altfel ntoarce !*##.
Pentru a 0loca un mutex se folosete una din funciile de ateptare.
Pentru a eli0era un mutex:
/55# +elease@utex(
H!"#$ '@utex
89
Funcia ntoarce n caz de succes o valoare diferit de zero sau zero n caz de eec.
Pentru a crea sau pentru a o0ine un descriptor pentru un semafor avem funciile:
H!"#$ %reate)emap'ore(
#P)$%*+,&-.&&+,/*&$) lp)emap'orettri0utes1
#5!Y l,nitial%ount1
X
%onsultai F)Hnc'ronization 50ject )ecuritH and ccess +ig'tsF din @)"! pentru detalii.
#5!Y l@aximum%ount1
#P%&)&+ lp!ame
89
H!"#$ 5pen)emap'ore(
"75+" d3"esiredccess1
/55# 0,n'eritHandle1
#P%&)&+ lp!ame
89
Parametrii au semnificaie asemntoare cu cei ai funciilor pentru evenimente i
mutexuri. par n plus doi parametrii care specific valoarea iniial a semaforului i
valoarea maxim pe care o poate avea acesta.
Pentru a crete contorul unui semafor cu o anumit valoare avem funcia
+elease)emap'ore:
/55# +elease)emap'ore(
H!"#$ ')emap'ore1
#5!Y l+elease%ount1
#P#5!Y lpPrevious%ount
89
')emap'ore = descriptorul semaforului.
l+elease%ount = valoarea cu care va fi crescut contorul semaforului. 6aloarea
tre0uie s fie mai mare dect zero i contorul nu tre0uie s creasc mai mult dect
valoarea maxim.?n caz contrar funcia ntoarce F#)$.
lpPrevious%ount = un pointer la o varia0il n care va fi salvat valoarea
anterioar a contorului. Poate fi !*##.
?ntoarce zero n caz de eec i o valoare diferit de zero altfel.
Funcii de Ateptare
?n aceast seciune vor fi prezentate doar cteva din funciile de ateptare.
Pentru a atepta dup un singur o0iect1 avem:
"75+" 7aitFor)ingle50ject(
H!"#$ 'Handle1
"75+" d3@illiseconds
89
'Handle = un descriptor al o0iectului dup care se ateapt. "ac descriptorul este
nc'is n timpul ateptrii1 comportamentul funciei nu este specificat.
d3@illiseconds = intervalul de timp n care se ateapt. "ac este zero1 funcia
testeaz starea o0iectului i ntoarce imediat. "ac este ,!F,!,&$ atunci poate
atepta la nesfrit.
"ac funcia reuete1 valoarea ntoars va indica ce eveniment a fcut ca funcia s
termine ateptarea. Poate avea una din valorile:
7,&./!"5!$" = Firul proprietar al o0iectului specificat iSa terminat
execuia fr aSl eli0era. Firul apelant devine proprietar al o0iectului1 starea
acestuia devenind nesemnalizat.
7,&.5/[$%&.> = starea o0iectului este semnalizat.
7,&.&,@$5*& = a expirat intervalul de timp specificat i starea o0iectului
este nesemnalizat.
?n caz de eec ntoarce 7,&.F,#$".
Funcia 0loc'eaz firul apelant pn cnd expir intervalul specificat sau pn cnd
o0iectul specificat devine semnalizat.
Pentru a atepta mai multe o0iecte:
"75+" 7aitFor@ultiple50jects(
"75+" n%ount1
const H!"#$O lpHandles1
/55# 07aitll1
"75+" d3@illiseconds
89
n%ount = numrul de descriptori din vectorul lpHandles. !umrul tre0uise s fie
mai mic sau egal cu @G,@*@.7,&.5/[$%&).
lpHandles = adresa de nceput a unui vector de descriptori. !u poate conine un
descriptor de mai multe ori. "ac un descriptor este nc'is n timpul ateptrii1
comportamentul este nespecificat. Pentru 7indo3s @eABCABD: nici un descriptor
nu tre0uie s fi fost o0inut cu ajutorul "uplicateHandle.
07aitll = dac acest parametru este &+*$ se ateapt ca starea tuturor
o0iectelor s devin semnalizat. ltfel1 se ateapt dup oricare dintre o0iecte.
d3@illiseconds = intervalul care se ateapt. 2ero i ,!F,!,&$ au aceeai
semnificaie ca la ateptarea dup un singur o0iect.
?n caz de succes1 valoarea ntoars va indica ce anume a cauzat terminarea ateptrii:
7,&.5/[$%&.> la (7,&.5/[$%&.> V n%ount = E8 = dac 07aitll este
&+*$1 valoarea indic faptul c toate o0iectele au fost semnalizate. "ac
07aitll este F#)$1 valoarea ntoars minus 7,&.5/[$%&.> indic indexul
cel mai mic al unui o0iect care a nc'eiat ateptarea.
7,&./!"5!$".> la (7,&./!"5!$".> V n%ount = E8 = "ac
07aitll este &+*$1 valoarea indic faptul c toate o0iectele sunt fie semnalizate
sau a0andonate1 cel puin unul fiind a0andonat. "ac 07aitll este F#)$1
valoarea ntoars minus 7,&./!"5!$".> indic indexul o0iectului care a
finalizat ateptarea.
7,&.&,@$5*& = expirat timpul fr ca cealalt condiie de finalizare a
ateptrii s fie satisfcut.
?n caz de eec1 funcia ntoarce 7,&.F,#$".
$xemplu de folosire a evenimentelor1 mutexSurilor i a funciilor de ateptare:
Iinclude Jstdio.'K
Iinclude Jprocess.'K
Iinclude JmemorH.'K
Iinclude Jmalloc.'K
Iinclude Jstdli0.'K
Iinclude J3indo3s.'K
H!"#$ evast:U<9
void aduna(voidO args89
voidO punergumente(int v:<1 int nr$lemente1 int fir1 int nrFire8L
voidO temp M malloc(sizeof(intO8 V ; O sizeof(int889
int inceput M (nr$lemente A nrFire8 O fir 9
int Opinceput M Rv:inceput<9
int elemente M (nr$lemente A nrFire8 O (fir V E8 S inceput9
memcpH(temp1 Rpinceput1 sizeof(intO889
memcpH((c'arO8temp V sizeof(intO81 Relemente1 sizeof(int889
memcpH((c'arO8temp V sizeof(intO8 V sizeof(int81 Rfir1 sizeof(int889
return temp9
Q
int suma M >9
H!"#$ '@utexE1 '@utex;9
void main(8L
int v:< M LT1E1;1U1S;1Z1;;1EE1SEQ9
int n M B9
AA %reate a mutex 3it' no initial o3ner.
'@utexE M %reate@utex(
!*##1 AA no securitH attri0utes
F#)$1 AA initiallH not o3ned
Fmutex pentru printfF89 AA name of mutex
if ('@utexE MM !*##8
L
$xitProcess(>89
AA %'ec4 for error.
Q
'@utex; M %reate@utex(
!*##1 AA no securitH attri0utes
F#)$1 AA initiallH not o3ned
Fmutex pentru sumaF89 AA name of mutex
if ('@utex; MM !*##8
L
$xitProcess(>89
AA %'ec4 for error.
Q
int nrFire M T9
for( int iM>9 iJ nrFire9 iVV8L
voidO args M punergumente(v1 n1 i1 nrFire89
evast:i<M %reate$vent(
!*##1 AA no securitH attri0utes
&+*$1 AA manualSreset event o0ject
F#)$1 AA initial state is nonsignaled
!*##89 AA unnamed o0ject
if (evast:i< MM !*##8 L
printf(F%reate$vent error: NdWnF1 Yet#ast$rror(8 89
$xitProcess(>89
Q

.0egint'read(aduna1 >1 args89
Q
7aitFor@ultiple50jects(
nrFire1 AA num0er of o0jects in arraH
evast1 AA arraH of o0jects
&+*$1 AA 3ait for all
,!F,!,&$89
printf(Fsuma este NdWnF1 suma89
Q
void aduna(voidO args8L
intO vector9
int fir9
int nr9
memcpH(Rvector1 args1 sizeof(intO889
memcpH(Rnr1 (c'arO8args V sizeof(intO81 sizeof(int889
memcpH(Rfir1(c'arO8args V sizeof(intO8 V sizeof(int81 sizeof(int889
free(args89
7aitFor)ingle50ject('@utexE1 ,!F,!,&$89
printf(Ffirul Nd cu Nd elemente de adunatWnF1 fir1 nr89
printf(FWt$lementele sunt:F89
for (int i M >9 i J nr9 iVV8
printf(F Nd F1 vector:i<89
printf(FWnF89
+elease@utex('@utexE89
int temp M >9
for ( i M >9 i J nr9 iVV8
temp VM vector:i<9
7aitFor)ingle50ject('@utex;1 ,!F,!,&$89
suma VM temp9
+elease@utex('@utex;89
)et$vent(evast:fir<89

Q
Probleme Propuse.
E. ) se determine dac un element apare ntrSun vector oarecare1 folosind n
procesoare.
;. ) se determine pe ce poziii apare un element ntrSun vector oarecare1 folosind n
procesoare.
T. 5 resurs poate fi utilizat de dou tipuri de procese: al0e i negre. tunci cnd
resursa este folosit de procese al0e ea nu mai poate fi folosit de procese negre.
$ste vala0il i reciproca. ) se implementeze accesul la resurs1 evitnduSse
nfometarea.
U. ) se sorteze elementele unui vector cu n procesoare.
D. ) se genereze toate numerele prime mai mici dect o anumit valoare1 folosind n
procesoare.
Z. ) se coordoneze semafoarele de la captul unui tunel cu o singur 0and1
folosinduSse de senzorii de la fiecare capete care semnalizeaz intrarea i ieirea
mainilor1 astfel nct s nu se permit intrarea pe la un capt ct timp mai sunt
maini n tunel mergnd n sens invers. @ainile s fie simulate cu ajutorul firelor
de execuie.

S-ar putea să vă placă și