spora

93
1 1. NOŢIUNI DE BAZĂ ŞI CLASIFICĂRI 2 2. Noţiuni şi termeni din domeniul resurselor tehnice 2 3. Noţiuni şi termeni din domeniul sistemelor de operare 2 4. Tipuri de sisteme de operare, obiective şi funcţii 3 5. Exemple de sisteme de operare 3 6. Cazul calculatoarelor personale 3 7. Comanda unor procese industrial 4 8. Sisteme tranzacţionale 4 9. Sisteme în timp partajat 4 10. SISTEMUL DE OPERARE ŞI PROCESELE 5 11. MAŞINĂ IERARHICĂ ŞI MAŞINĂ EXTINSĂ 5 12. ALTE PUNCTE DE VEDERE ASUPRA SISTEMELOR DE OPERARE 5 13. Abordare funcţională 6 14. Abordare din punctul de vedere al interfeţei cu utilizatorul 6 15. EVOLUŢIA SISTEMELOR DE OPERARE 6 16. De la "poartă deschisă " la tratarea pe loturi 6 17. Multiprogramarea şi partajarea timpului 7 18. Organizarea intrărilor - ieşirilor în memorii tampon 7 19. Multiprogramarea 8 20. Sisteme cu timp partajat 8 21. Windows, Unix şi alte sisteme 8 22. SО UNIX şi standardele sistemelor deschise 9 23. OSF-1 şi alte variante UNIX 9 24. Standarde UNIX 9 25. Sisteme de operare cu micronucleu 10

description

fd

Transcript of spora

Page 1: spora

1

1. NOŢIUNI DE BAZĂ ŞI CLASIFICĂRI 2

2. Noţiuni şi termeni din domeniul resurselor tehnice 2

3. Noţiuni şi termeni din domeniul sistemelor de operare 2

4. Tipuri de sisteme de operare, obiective şi funcţii 3

5. Exemple de sisteme de operare 3

6. Cazul calculatoarelor personale 3

7. Comanda unor procese industrial 4

8. Sisteme tranzacţionale 4

9. Sisteme în timp partajat 4

10. SISTEMUL DE OPERARE ŞI PROCESELE 5

11. MAŞINĂ IERARHICĂ ŞI MAŞINĂ EXTINSĂ 5

12. ALTE PUNCTE DE VEDERE ASUPRA SISTEMELOR DE OPERARE 5

13. Abordare funcţională 6

14. Abordare din punctul de vedere al interfeţei cu utilizatorul 6

15. EVOLUŢIA SISTEMELOR DE OPERARE 6

16. De la "poartă deschisă " la tratarea pe loturi 6

17. Multiprogramarea şi partajarea timpului 7

18. Organizarea intrărilor - ieşirilor în memorii tampon 7

19. Multiprogramarea 8

20. Sisteme cu timp partajat 8

21. Windows, Unix şi alte sisteme 8

22. SО UNIX şi standardele sistemelor deschise 9

23. OSF-1 şi alte variante UNIX 9

24. Standarde UNIX 9

25. Sisteme de operare cu micronucleu 10

Page 2: spora

2

1.NOŢIUNI DE BAZĂ ŞI CLASIFICĂRI

Sistem de operare- destinaţia este administrarea (gestiunea, controlul) resurselor tehnice

principale şi asigurarea unei interfeţe comode (plăcute, prieteneşti) între utilizator şi

calculator.(Sistem de operare înţelegem modulele program ale unui sistem de calcul, care

administrează resursele tehnice (procesoare,memoria operativă şi secundară, dispozitive de

intrare/ieşire, fişiere)).Functii SO:utilizarea resurselor hardware în scopuri speciale poate fi

necesar să se creeze un sistem de operare propriu sau să se introducă modificări în sistemul

existent;de alegerea corectă a sistemului de operare şi a versiunii concrete poate depinde

viabilitatea şi eficacitatea sistemului de calcul;este ideal ca utilizatorul să interacţioneze cu

sistemul de operare cunoscând toate subtilităţile ultimului, deoarece sistemul de operare este

un intermediar între calculator şi utilizator;

2.Noţiuni şi termeni din domeniul resurselor tehnice.

Un calculator constă dintr-un ansamblu de componente funcţionale fizice şi logice, care

cooperează pentru a satisface cerinţele utilizatorilor privind introducerea, stocarea,

prelucrarea, transmisia şi căutarea informaţiilor. Suportul fizic (resurse tehnice, hardware)

constituie nivelul inferior al sistemului de calcul construit pe baza unor componente

electronice, magnetice, optice, mecanice etc. Funcţii esenţiale ale calculatorului: iniţializarea

(bootup), introducerea datelor, procesarea datelor, stocarea datelor şi extragerea

rezultatelor. Prin structura unui calculator vom înţelege componentele (dispozitivele) care

formează calculatorul şi legăturile dintre ele. Componentele principale sunt: procesorul,

memoria, unităţile de stocare pe termen lung, dispozitivele de intrare-ieşire (tastatura,

display-ul, mouse-ul etc.). Componentele principale se conectează la placa de bază direct sau

prin conectoare special.interactionind si cu alte elemente.Mai mentionam notiuni ca

:,magistrala interne de date, magistrala externe de date, memorie, ceas electronic .

3.Noţiuni şi termeni din domeniul sistemelor de operare

Un sistem de operare este un ansamblu de programe de control şi de serviciu care

ghidează un calculator în executarea sarcinilor sale şi asistă programele de aplicaţie şi

utilizatorul prin intermediul anumitor funcţiuni. Natura funcţiilor şi modul în care acestea

sunt realizate determină atributele care caracterizează un sistem de operare: timpul de

răspuns, simultaneitatea utilizării, eficienţa, partajarea şi protecţia, generalitatea,

flexibilitatea, extensibilitatea, fiabilitatea şi disponibilitatea, transparenţa şi vizibilitatea.

Timpul de răspuns exprimă durata intervalului delimitat de lansarea unei cereri de serviciu

şi achitarea acesteia de către sistemSimultaneitatea utilizării măsoară gradul în care un

sistem poate să execute în acelaşi timp mai multe lucrări.Eficienţa măsoară proprietatea unui

sistem de a folosi în mod optim resursele de care dispune.Partajarea şi protecţia

caracterizează nivelul la care utilizatorii au posibilitatea să utilizeze în comun informaţia

prezentă în sistem şi nivelul la care pot să comunice între ei, în deplină siguranţă

Generalitatea, flexibilitatea, extensibilitatea măsoară gradul în care un sistem poate fi

Page 3: spora

3

folositor şi adaptabil unui context specific Resursele program reprezintă seturi de programe

şi date utilizate pentru soluţionarea anumitor probleme. Multiprogramarea este un termen

utilizat în cazul unui sistem în care pot exista simultan câteva procese în stare de execuţie.

Resursele hardware de protecţie sunt utilizate cel mai des pentru controlul accesării

memoriei. Resursele hardware de întrerupere permit sistemului de operare să coordoneze

operaţiile simultane

4.Tipuri de sisteme de operare, obiective şi funcţii

Pot fi evidenţiate sisteme de operare :secvenţiale(execută la un moment dat un singur

program, care trebuie terminat înainte de a lua un alt program în consideraţie),cu

multiprogramare(acceptă la un moment dat mai multe programe în memoria centrală,

acestea aflându-se în diverse stadii de execuţie.)cu prelucrare multiplă(dispune de mai

multe procesoare, care pot să execute simultan unul sau mai multe programe),în timp real,

etc. Obiective-maximizarea eficienţei sistemului de calcul şi a satisfacţiei utilizatorilor,

cererea de minimizare a posibilităţii de apariţie a unor erori , de maximizare a transparenţei

sistemului de operare, garantarea securităţii datelor, optimizarea controlului comunicaţiilor ,

efortului concepţie-realizare a sistemului. Un sistem de operare are urm functii:să păstreze

informaţia despre starea fiecărei resurse să ia decizia cărui proces să i se aloce resursa, în ce

cantitate şi când să aloce resursa şi la momentul respectiv să o retragă.

5.Exemple de sisteme de operare

Sistemele de operare pot fi utilizate la calculatoarele personale,comanda unor procese

industriale,sisteme tranzacţionale(care include volume de date importante),sisteme în timp

partajat.

6.Cazul calculatoarelor personale

Configuraţia cea mai simplă a unui calculator personal (PC) include o unitate centrală, o

memorie principală, un display, o tastatură şi un mouse. Sistemul de operare va acorda

servicii prin intermediul unui limbaj special, numit limbaj de comandă.Exemplu de

secvenţe tipice de activităţi în cazul unui PC:elaborarea unui program;introducerea

programului cu ajutorul tastaturii şi a unui editor de texte;executarea programului

introducându-se datele necesare de la tastatură şi extrăgând rezultatele la display sau

imprimantă;modificarea programului, dacă rezultatele nu sunt satisfăcătoare şi repetarea

execuţiei;perfectarea versiunii finale a programului, inclusiv documentarea la necesitate a

acestuia;exploatarea unui program;cererea de executare a unui program deja existent. Într-un

atare sistem funcţia partajare a resurselor am considerat-o lipsă, or PC-ul este folosit de un

singur utilizator care are controlul total asupra acestuia. Funcţiile principale vizibile ale

sistemului de operare constau în administrarea fişierelor, realizarea operaţiilor de

intrare/ieşire şi interpretarea comenzilor provenite de la interfaţa utilizator-sistem de

operare.Pentru acest tip de sisteme cele mai importante caracteristici

sunt:fiabilitatea;eficacitatea;simplitatea utilizării;facilitatea extensibilităţii prin adăugarea

unor utilite noi sau adaptarea la periferice noi.

7.Comanda unor procese industriale

Page 4: spora

4

Ex:Fie la o uzină chimică sunt utilizate doua produse iniţiale A şi B pentru sinteza

produsului C .Procesul de producere este comandat de un calculator care îndeplineşte

următoarele funcţii:Reglare,Înregistrare. Securitate. Acest mod de funcţionare introduce

unele restricţii.măsurările -făcute periodic; fie T valoarea intervalului de timp dintre două

măsurări consecutive (perioada de eşantionare), iar t - timpul total de prelucrare a datelor de

către calculator .Sistemul va funcţiona doar în cazul respectării relaţiei de restricţionare t

T.Securitatea sistemului are prioritate maximăFuncţiile principale ale sistemului de operare

sunt:acţionarea organelor externe;evidenţa timpului real ;reacţia la evenimentele exterioare

(oprire de urgenţă);gestiunea informaţiilor (păstrarea şi întreţinerea fişierului jurnalului de

bord).În cazul acestor sisteme caracteristica principală este fiabilitatea, or rezultatele unei

funcţionări neadecvate pot fi catastrofale. Sistemul trebuie să garanteze un serviciu minim în

cazul unor căderi în pană a dispozitivelor tehnice, unor evenimente accidentale sau erori

umane.

8.Sisteme tranzacţionale

Caracteristicile principale ale sistemelor cu tranzacţii sau tranzacţionale sunt

următoarele:sistemul gestionează un set de informaţii sau baze de date, care pot atinge

volume importante;asupra acestor informaţii pot fi executate un anumit număr de operaţii

predefinite, sau tranzacţii, adesea interactive;sistemul este dotat cu un mare număr de puncte

de acces şi un mare număr de tranzacţii se pot derula simultan.Ca exemplu pot fi menţionate

sistemele de rezervare a biletelor de tren sau avion, de gestionare a conturilor

bancare,Restricţiile sunt în primul rând legate de integritatea şi coerenţa internă a

informaţiilor, care formează bazele de date. Calităţile obligatorii ale unui sistem tranzacţional

sunt disponibilitatea şi fiabilitatea; pentru unele sisteme poate fi importantă şi toleranţa la

defecţiuni. O caracteristică importantă ale sistemelor tranzacţionale este multitudinea

activităţilor paralele, iar în multe cazuri şi repartizarea geografică a componentelor.

9.Sisteme în timp partajat

Destinaţia principală a unor astfel de sisteme este furnizarea serviciilor necesare unei

mulţimi de utilizatori, fiecare dintre ei beneficiind:de servicii echivalente serviciilor unui

calculator individual;de servicii legate de existenţa unei comunităţi de utilizatori: partajarea

informaţiilor, comunicaţii între utilizatori.Problemele care apar datorită conceptului de

partajare a timpului sunt o combinaţie a problemelor existente în cazul unui calculator

individual cu cele din sistemele tranzacţionale şi pot fi clasificate după cum

urmează:definirea maşinii virtuale oferite fiecărui utilizator;partajarea şi alocarea resurselor

fizice comune: procesoare, memorii, organe de comunicaţie;gestionarea informaţiilor

partajate şi a comunicaţiilor.Caracteristicile obligatorii unui atare sistem combină în egală

măsură calităţile unui sistem de operare al unui calculator individual şi al unui sistem

tranzacţional: disponibilitatea, fiabilitatea, securitatea, exploatarea optimă a caracteristicilor

resurselor fizice, calitatea interfeţei şi serviciilor utilizatorului, facilitatea adaptării şi

extensibilităţii.

Page 5: spora

5

10.SISTEMUL DE OPERARE ŞI PROCESELE

Proces-o suită temporală de execuţii de instrucţiuni, fiind o entitate de bază în

descrierea sau analiza funcţionării unui sistem. Evoluţia în timp a unui proces presupune un

consum de resurse, dictat de natura şi complexitatea instrucţiunilor de executat. Orice

utilizare a unei resurse este asociată, la un moment dat, unui proces şi procesul respectiv îşi

asumă răspunderea utilizării acestei resurse. Ciclul de viaţă a unui proces poate fi reprezentat

printr-un set de stări ale procesului şi trecerea de la o stare la alta. Vom evidenţia trei stări

elementare ale unui proces: proces ales (sau exe) – procesului i s-a alocat un procesor, este

în curs de execuţie, proces blocat – procesul aşteaptă să se producă un anumit eveniment, a

cărui apariţie este indispensabilă, proces eligibil – procesul are la dispoziţie toate resursele

necesare lipsă fiind doar procesorul, Sistemul de operare este acea componentă, care va ghida

procesul prin toate aceste stări. pentru modelarea procesului real au fost adăugate trei stări

suplimentare: prezentare –utilizatorul prezintă sistemului sarcina, sistemul trebuie să

reacţioneze la cererea utilizatorului, păstrare –sarcina este reprezentată în formă internă, dar

resursele nu sunt încă alocate,terminare – calculele corespunzătoare procesului au luat

sfârşit, toate resursele alocate procesului pot fi eliberate şi întoarse istemului

11.MAŞINĂ IERARHICĂ ŞI MAŞINĂ EXTINSĂ

Setul de instrucţiuni realizat hardware împreună cu instrucţiunile suplimentare ale

sistemului de operare formează sistemul de comenzi al maşinii extinse.O masina extinsa e

formata din citeva procese,masina goala si sistemul de operare.Notiunuea de masine extinsa

în cazul sistemelor de operare, poate fi utilizat în două nivele, astfel conduce la noţiunea de

maşină ierarhică. Primul nivel - funcţiile cheie, utilizate de majoritatea modulelor de

sistem, pot fi realizate în cadrul unei maşini extinse interne şi Nivelul doi - unele module

pot fi executate în cadrul unei maşini extinse externe. Modulele sistemului, plasate în cadrul

maşinii extinse, spre deosebire de modulele care aparţin straturilor proceselor, formează

nucleul sistemului de operare

12.ALTE PUNCTE DE VEDERE ASUPRA SISTEMELOR DE OPERARE:

Abordare din punctul de vedere al interfeţei cu utilizatorul,Abordare funcţională:

13.Abordare funcţională:

Destinaţia principală a unui sistem de operare pentru categoria de utilizatori obişnuiti

la care noţiuni cum ar fi administrarea memoriei cu paginaţie sau driverele dispozitivelor nu

semnifică prea multe,este punerea la dispoziţie a unui set de programe care ar ajuta în

Page 6: spora

6

formularea şi rezolvarea problemelor concrete. Abordarea sistemelor de operare din acest

punct de vedere (abordare funcţională) poate conduce la confundarea lor cu unele programe,

utile şi foarte importante (translatoare, biblioteci, medii integrate, etc.). Pentru a evita

posibilitatea apariţiei unei astfel de probleme aceste programe, de obicei, nu sunt

considerate componente ale sistemului de operare.

14.Abordare din punctul de vedere al interfeţei cu utilizatorul

Interfaţa sistemului de operare cu utilizatorul prezintă un interes aparte. Progresul în

acest domeniu este spectaculos, dacă vom lua în consideraţie că în primele sisteme

utilizatorul era obligat să indice în mod explicit şi manual fiecare pas cu ajutorul Job

Control Language Microprocesoarele şi memoriile anilor ’70 au pus problema lansării pe

piaţă a calculatoarelor personale (PC) cu toate consecinţele respective. Una din consecinţe

este şi interfaţa utilizator-calculator, sistemul de operare devenind până la urmă responsabil

de aceasta. Interfaţa grafica a utilizatorului (Graphical User Interface - GUI) a apărut mai

întâi ca un complement al sistemului de operare (pentru MS DOS - Windows 1, Windows 2

sau chiar Windows 3, de exemplu), pentru ca mai apoi să fie integrată în cadrul sistemului .

15.EVOLUŢIA SISTEMELOR DE OPERARE

O analiză cronologică a dezvoltării sistemelor de operare este greu de realizat,

deoarece multe din principiile foarte importante au fost realizate pentru prima dată cu mult

înainte de a deveni acceptate. Primele sisteme erau caracterizate prin prelucrarea

secvenţială a taskurilor. Timpul de execuţie a programelor era relativ mare, instrumentele

de depanare – primitive, fiecare programator îşi încărca în mod individual programul

(pachetul de cartele perforate), apăsa butoane, controla conţinutul locaţiunilor de memorie,

etc. (1950 – 1956).Primele încercări de prelucrare pe loturi (1956 – 1959).Odată cu

creşterea complexităţii calculatoarelor, îndeosebi în ceea ce consta administrarea

dispozitivelor periferice, au fost propuse sisteme supervizoare (1959 – 1963). care se aflau

în memoria calculatorului în mod constant şi acordau utilizatorilor servicii în gestiunea

operaţiilor de intrare/ieşire Au urmat apoi sistemele cu multiprogramare, menite la început

să rezolve problema concordării vitezei de calcul a unităţii centrale şi a perifericelor. După

1965 au apărut primele sisteme cu partajare a timpului Memoria virtuală şi maşinile

virtuale sunt nişte principii care nici până astăzi nu au fost exploatate până la capăt.

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.

Specificaţiile sistemelor de operare au fost în mare măsură standardizate, diversitatea SO

devine tot mai mică, mulţi specialişti exprimându-şi îngrijorarea de o posibilă monopolizare

a domeniului în viitorul apropiat.

16.De la "poartă deschisă " la tratarea pe loturi

Primele calculatoare nu dispuneau de sisteme de operare. Fiecărui utilizator i se

rezerva pentru un timp determinat calculatorul cu toate resursele acestuia. Interacţiunea era

Page 7: spora

7

directă, programul şi datele fiind introduse în mod manual sub formă de zerouri şi unităţi.

Utilitele care au apărut aveau destinaţia de a asista elaborarea programelor (asambloare,

compilatoare, etc.) sau de a facilitata operaţiile de intrare-ieşire.Acest mod de exploatare,

numit "poartă deschisă" ,era de o eficacitate minimă, dispozitive foarte costisitoare fiind

utilizate ineficient. Din această cauză la sfârşitul anilor '50 au apărut primele "monitoare de

înlănţuire" - programe care permiteau executarea secvenţială a unui set de lucrări, pregătite

anticipat, trecerea de la o lucrare la alta fiind automatizată.Funcţia principală a unui atare

sistem era gestiunea resurselor: memoria, procesorul, intrarea-ieşirea. dând posibilitatea

sporirii la maximum a randamentului calculatorului principal.Deşi utilizarea monitoarelor

de înlănţuire a ameliorat notabil randamentul utilizării procesorului, acest randament

rămânea foarte scăzut din cauza că procesorul nu era eliberat în timpul operaţiilor de

intrare-ieşire. O soluţionare ar fi constat în utilizarea a două calculatoare - unul (principal)

pentru executarea programelor şi altul (auxiliar) pentru operaţiile de intrare-ieşire. O

planificare adecvată a executării lucrărilor permitea utilizarea celor două calculatoare în

paralel, dând posibilitatea sporirii la maximum a randamentului calculatorului principal.

17.Multiprogramarea şi partajarea timpului

Utilizarea principiului multiprogramării sau partajarea memoriei între mai mulţi

utilizatori a permis o utilizare şi mai bună a procesorului central. Exploatarea unui

calculator conform principiului timpului partajat oferă utilizatorilor posibilităţi analogice

unui calculator individual, permiţând beneficiul unor servicii comune la un preţ redus.

18.Organizarea intrărilor - ieşirilor în memorii tampon

Un canal este un procesor specializat în executarea autonomă a operaţiilor de intrare-

ieşire, paralel cu procesul de prelucrare a informaţiilor. Viteza de lucru a organelor

periferice este relativ mică din cauza unor dispozitive mecanice care intră în componenţa

acestora. Pentru excluderea influenţei perifericelor asupra vitezei de lucru a sistemului de

calcul s-a propus să se păstreze în memorie în anumite zone tampon datele de intrare (care

vor fi utilizate la necesitate) şi rezultatele (care vor fi imprimate în mod autonom) mai

multor lucrări. Schema intrari/iesiri in memoria tampon

Pentru a exclude utilizarea ineficientă a memoriei operative prin formarea zonelor-

tampon, acestea erau organizate în memoria secundară de capacitate înaltă, transferurile

între aceste două nivele ale memorie fiind de asemenea comandate de un canal.Deşi

utilizarea memoriilor tampon prezintă o serie de avantaje în vederea sporirii randamentului

dispozitivelor calculatorului, totuşi două momente negative pot fi menţionate:atunci când

lucrarea în curs de execuţie are nevoie de nişte date unitatea centrală rămâne inactivă pe

toată perioada citirii acestora;o lucrare de scurtă durată, sosită în timpul execuţiei unei

lucrări "lungi", trebuie să aştepte terminarea acesteia din urmă.

Intrăr

Lucrări

la Debit Debit

Debit Rezulta

te la

Prelucrarea Ieşire Fig.1.12. Buferizarea intrărilor-

Page 8: spora

8

19.Multiprogramarea

Multiprogramarea implica prezenţa simultană în memoria operativă a mai multor

programe sau părţi de programe.

Schema de functionare-multiprogramare:

Avantajele şi restricţiilemultiprogramării :un sistem cu multiprogramare este mai

complicat pentru că el trebuie să asigure partajarea memoriei şi protecţia reciprocă a

programelor;multiprogramarea necesită dispozitive speciale pentru reactivarea programelor

şi protecţia memoriei;un sistem cu multiprogramare asigură o utilizare mai uniformă a

diferitor resurse: unitatea centrală, memoria, organele de intrare-ieşire;multiprogramarea

permite reducerea timpului de răspuns în cazul lucrărilor de durată mică într-un sistem cu

prelucrare secvenţială.

20.Sisteme cu timp partajat

Un sistem de operare cu partajarea timpului trebuie să garanteze fiecărui utilizator un

timp acceptabil de răspuns. Acest rezultat este obţinut prin alocarea succesivă a

procesorului pentru tranşe de timp foarte mici (cuante) programelor utilizatorilor.

Activitatea unui utilizator conţine două componente: timpul de reflecţie (gândire), în care

utilizatorul elaborează, propune subiecte de lucru, introducând în calculator informaţii şi

timpul de aşteptare, când aşteaptă executarea de către sistem a serviciului cerut.

Dezvoltarea sistemelor de operare cu partajarea timpului a pus în evidenţă importanţa

interacţiunii om-calculator.

21.Windows, Unix şi alte sisteme

Paralel cu evoluţia tehnică şi funcţională a sistemelor de operare a avut loc şi o

importantă evoluţie conceptuală, care a permis o mai bună înţelegere a funcţionării

sistemelor de operare şi a condus la elaborarea unor metode proprii de concepere.Debutul

unei cercetări ştiinţifice a sistemelor de operare poate fi considerat anul 1964, care a

succedat o etapă importantă de dezvoltare tehnică: primele sisteme cu partajare a timpului

(Thor, CTSS), anunţarea seriei IBM 360 şi introducerea canalelor de intrare-ieşire, prima

memorie paginată (Atlas), etc.În perioada 1965-1968 au fost elaborate noţiunile necesare

conştientizării gestionării activităţilor fizice sau conceptuale paralele: proces secvenţial,

formularea şi soluţionarea unor probleme de excludere mutuală, sincronizarea şi inventarea

semaforului.Sunt propuse primele metode de specificare şi control al validităţii

sincronizărilor.In 1962 apare prima memorie paginată.În 1965 este fundamentată noţiunea

de segmentare.În 1966 este propus un model de arhitectură pentru calculatoare cu partajare

a timpului.Problemele partajării şi protecţiei informaţiei, alocării resurselor conduc la

noţiunea de memorie virtuală, care permite izolarea mecanismelor de gestionare a

ansamblului “memorie principală - memorie secundară”, lăsând utilizatorilor simpli

impresia unui spaţiu de adresare uniform (contiguu). Au fost introduse noţiunile de

modularitate şi structurare ierarhică, obiect, etc.Astăzi sistemele de operare în sensul

tradiţional de concepere sunt obiectul unor elaborări industriale, decât de cercetare.Aceasta

este datorat atât achiziţionării unei rezerve extraordinare de metode şi algoritmi, cât şi

Page 9: spora

9

standardizării stricte a funcţiilor şi interfeţelor sistemelor de operare.(Windows,Unix sunt

SO care au evoluat cu timpul)

22.SО UNIX şi standardele sistemelor deschise

Sistemul de operare UNIX, primul sistem mobil care asigură un mediu fiabil de

dezvoltare şi utilizare a softului de aplicaţie, este fundamentul practic de elaborare a

sistemelor fizico-logice deschise. Implementarea largă a sistemului de operare UNIX a

permis trecerea de la declararea sistemelor deschise la dezvoltarea practică a acestui

concept.Pot fi evidenţiate câteva versiuni ale SO UNIX, care diferă atât prin realizare, cât şi

prin interfeţe şi semantic. Sistemul de operare UNIX, primul sistem mobil care asigură un

mediu fiabil de dezvoltare şi utilizare a softului de aplicaţie, este fundamentul practic de

elaborare a sistemelor fizico-logice deschise. Implementarea largă a sistemului de operare

UNIX a permis trecerea de la declararea sistemelor deschise la dezvoltarea practică a

acestui concept. Modulele sursă ale SO UNIX au fost scrise de către colaboratorii

companiei AT&T care mai tirziu a creat compania USL (UNIX System Laboratories), care

avea în şarjă exclusivă dezvoltarea şi susţinerea modulelor sursă ale SO UNIX.Versiunile

UNIX sunt: UNIX System V 4.0, UnixWare 2.0 bazată pe System V 4.2,versiunea SVR

4.2,s.a. Pe parcursul a mai multor ani sistemul de operare de bază al companiei Sun a fost

UNIX BSD,care a introdus o serie de modificari si extensii in versiunea UNIX System V

4.0.

23.OSF-1 şi alte variante UNIX

Open Software Foundation (OSF) a fost prima companie comercială, care a încercat

elaborarea SO UNIX în baza micronucleului Mach. A fost creat sistemul de operare OSF-1,

care nu era în sens de licenţiere „curat”, deoarece folosea o parte a modulelor iniţiale din

SVR 4.0.Variantele SO UNIX, propuse de Universitatea din California, sunt o alternativă

reală pentru UNIX AT&T. Realizarea originală a SO UNIX pentru platformele Intel,

LINUX tot este o varianta UNIX.-un sistem de operare foarte popular în mediul studenţesc,

care are şi una din cele mai populare teleconferinţe în Internet. Odată cu ieşirea SO UNIX

pe piaţă şi creşterea substanţială nu numai a numărului de utilizatori, ci şi a numărului de

specialişti din toate colţurile lumii, care propuneau modificări şi chiar variante proprii, a

apărut necesitatea elaborării unor standarde, care ar conduce la sisteme compatibile.

Activitatea de standardizare a început cu mai mult de 10 ani în urmă,a obtinut rezultate, dar

inca este puţin probabil să se ajungă la finiş într-un viitor apropiat.

24.Standarde UNIX

Unul dintre primele standarde de-facto a fost cel publicat de USL pentru versiunea SO

UNIX System V Release 4 - System V Interface Definition (SVID). Majoritatea variantelor

comerciale respectau standardul SVID,care nu era un standart official. Cel mai popular

standard, adoptat de ISO definea cerinţele minime pentru componentele unui sistem de

operare.Pentru lumea UNIX este foarte important şi standardul limbajului de programare C,

Page 10: spora

10

adoptat mai întâi 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 apariţie

limbajul C şi sistemele de programare respective erau strâns legate de UNIX, componentele

bibliotecilor standard corespundeau exact mediului standard al SO UNIX.Mai menţionăm

standardul de-facto SPARC Complience Definition, propus de organizaţia SPARC

International, propunerea organizaţiei 88/Open pentru procesoarele RISC Motorola,

standardul sistemului de ferestre, susţinut de X Consorţium (Institutul de Tehnologie din

Massachussets) şi OSF/Motif, elaborat de Open Software Foundation

25.Sisteme de operare cu micronucleu

Micronucleul este partea minimă principală a unui sistem de operare, folosită pentru

asigurarea modularităţii şi transportabilităţii. Noţiunea de micronucleu a fost introdusă de

compania Next prin sistemul de operare cu micronucleul Mach.Nucleul acestui sistem de

operare, de dimensiuni mici, în jurul căruia se situau subsistemele executate în regim user,

trebuia să asigure o flexibilitate şi modularitate foarte înaltăutilizarea micronucleului Mach

a permis introducerea administrării mesajelor şi a unei serii de funcţii de serviciu orientate

pe obiecte, în baza cărora a fost creată o interfaţă grafică elegantă a utilizatorului cu

mijloace simple de configurare, administrare şi dezvoltare programUrmătorul SO cu

micronucleu a fost MS Windows NT, în care momentul principal declarat era, în afara

modularităţii, transportabilitatea.La tehnologia „micronucleară” au aderat si alte companii

renumite.

Page 11: spora

11

26.MODUL SECVENŢIAL DE EXECUŢIE A UNUI PROGRAM 12

27.Noţiuni fundamentale 12

28.Starea şi contextul procesorului 13

29.ÎNTRERUPERI, DEVIERI, APELAREA SUPERVIZORULUI 13

30.Activităţi asincrone 14

31.Mecanisme de comutare a contextului 14

32.Întreruperi 15

33.Devieri şi apelarea supervizorului 17

34.Exemple de sisteme de întreruperi 18

35.IMPLEMENTAREA MECANISMELOR DE COMUTARE A CONTEXTULUI 18

36.Utilizarea devierilor şi apelării supervizorului 19

37.Exemple de utilizare a întreruperilor 22

38.PROGRAMAREA OPERAŢIILOR DE INTRARE-IEŞIRE 26

39.Organizarea generală 26

40.Metode de comandă a perifericelor 29

41.Intrări-ieşiri buferizate în memorie 32

42.Încărcarea initial 40

43.Gestionarea activităţilor paralele. Exemple introductive 41

44.Administrarea tamponată a intrărilor-ieşirelor 41

45.Comanda unui proces industrial 43

46.Noţiune de proces secvenţial 44

47.Proces unic. Context 45

48.Relaţii între procese 46

49.Mulţimi de procese. Paralelism 46

50.Concurenţa proceselor. Resurse virtuale 48

Page 12: spora

12

26. MODUL SECVENŢIAL DE EXECUŢIE A UNUI PROGRAM

Nucleul unui calculator este format dintr-o memorie adresabilă, în care sunt păstrate

instrucţiunile şi datele programului, şi procesorul, care interpretează instrucţiunile. Instrucţiunile

şi datele se află în segmente distincte, prin segment înţelegând o mulţime de informaţii,

desemnate şi manipulate ca un tot întreg, care ocupă în memorie o suită contiguă de

amplasamente. Presupune că segmentele care conţin programul nu pot fi modificate în timpul

execuţiei acestuia.

Execuţia instrucţiunilor, care formează un program secvenţial, conduce la evoluţia stării

calculatorului. Evoluţia stării calculatorului poartă un caracter discret, starea este observabilă

doar în momente de timp numite puncte de observare, care corespund, de obicei, începutului şi

sfârşitului unei instrucţiuni. Unele instrucţiuni mai complexe pot conţine puncte observabile

intermediare.

27. Noţiuni fundamentale

Vom descrie un mecanism general pentru execuţia programelor secvenţiale, formate dintr-o

suită de activităţi, rezultate din execuţia unei proceduri sau corutine. Acest mecanism realizează

funcţiile următoare:

Salvarea şi restabilirea contextului la apelare şi retur,

Transmiterea parametrilor între procedurile apelantă şi apelată,

Administrarea unei zone de lucru proprii fiecărei proceduri, cu

permisiunea apelurilor recursive.

Exemplul 2.1. O procedură p (apelantă) provoacă execuţia unei proceduri q

(apelate) cu ajutorul unei secvenţe de apel care conţine următoarele etape:

Pregătirea parametrilor, transmişi de către procedura p procedurii q,

Salvarea parţială a contextului lui p, necesar la retur,

Înlocuirea contextului procedurii p prin contextul lui q.

La revenire din procedura q avem o schemă practic simetrică, doar contextul lui q fiind

pierdut:

Pregătirea rezultatelor, transmise de către procedura q procedurii p,

Restabilirea contextului procedurii p, salvat înainte de apel.

Exemplul 2.2. În cazul funcţionării în corutine (proceduri simetrice, recursie

mutuală – două proceduri se pot apela reciproc), procedurile apelantă şi apelată joacă

un rol simetric: secvenţa de retur este identică cu cea de apel. Activitatea care rezultă

din apelul unei proceduri p ia în calitate de context iniţial contextul salvat la ultimul

apel executat de p. Primul apel al unei proceduri trebuie să specifice valoarea iniţială

a contextului său.

Secvenţa de schimbare a contextului (reluarea) conţine următoarele etape (p este corutina

părăsită, q este cea reluată):

Page 13: spora

13

Pregătirea parametrilor, transmişi de către procedura p procedurii q,

Salvarea parţială a contextului lui p, care trebuie să fie regăsit la

reluare,

Restabilirea contextului salvat la ultimul abandon al lui q sau formarea

contextului iniţial în cazul primului apel.

28. Starea şi contextul procesorului

Starea procesorului este determinată de conţinutul registrelor acestuia. Registrele pot fi:

adresabile, numite registre generale, manipulate de programe,

registre speciale, de obicei grupate sub forma unor informaţii sintetice,

numite cuvânt de stare program sau cuvânt de stare a procesorului (în engleză,

program status word, PSW).

Cuvântul de stare a procesorului conţine informaţii, care pot fi clasificate astfel:

1) Informaţii referitoare la starea procesorului:

(a) Starea de execuţie. Procesorul se poate afla în starea activ în care

îndeplineşte instrucţii, sau în starea de aşteptare este în mod obligator rezultatul

unei întreruperi.

(b) Modul de funcţionare. Din considerente de protecţie este util să se

permită doar programelor sistemului de operare executarea unor instrucţiuni

anumite (speciale), programele utilizatorilor neavând acces la aceste instrucţiuni.

Astfel instrucţiunile rezervate modului supervizor pot fi numite privilegiate, aici

pot fi găsite instrucţiunile de intrare-ieşire şi cele legate de întreruperi şi protecţie.

(c) Masca întreruperilor.

2) Informaţii referitoare la contextul accesibil al memoriei şi drepturile de acces

asociate: tabele de segmente, indicatori de protecţie a memoriei, etc.

29. ÎNTRERUPERI, DEVIERI, APELAREA SUPERVIZORULUI

O întrerupere este comutarea contextului procesorului declanşată de o cauză externă

derulării instrucţiunii curente. Fizic, întreruperea înseamnă trimiterea unui semnal procesorului,

acest semnal provocând schimbarea stării unuia dintre indicatorii, consultaţi în cursul executării

fiecărei instrucţiuni. O întrerupere permite să cerem procesorului să suspende executarea

programului curent, din primul punct întreruptibil, şi să treacă la execuţia unui program

predefinit. Acesta din urmă este numit program de tratare a întreruperii.

Spre deosebire de o întrerupere, o deviere sau un apel al supervizorului sunt provocate de o

cauză legată direct de derularea instrucţiunii curente.

O deviere semnalizează o anomalie în derularea unei instrucţiuni, care prohibitează

executarea instrucţiunii. Originile pot fi diverse:

date incorecte, care conduc la imposibilitatea execuţiei corecte a instrucţiunii

(împărţirea la zero, de exemplu),

tentativa executării unei operaţii interzise de mecanismul de protecţie

(violarea protecţiei memoriei, executarea unei instrucţiuni privilegiate în modul program,

etc.),

Page 14: spora

14

instrucţiune neexecutabilă (cod neautorizat de operaţie, adresă în afara

memoriei existente, utilizarea unui dispozitiv opţional, care este lipsă în configuraţia dată,

etc.).

Un apel al supervizorului este o instrucţiune chemată să provoace o comutare a

contextului procesorului. Acest efect este analogic apelării unei proceduri, însă modificarea

contextului este mai profundă, fiindcă ea afectează întreg cuvântul de stare şi nu numai contorul

ordinal.

Destinaţia unui apel al supervizorului este de a permite apelarea unei proceduri a sistemului

de operare.

30. Activităţi asincrone

Prin asincronism înţelegem efectul care îl pot avea asupra derulării unei activităţi

anumite evenimente exterioare.

Numim protecţie reciprocă între activităţi o modificare mai profundă a contextului,

atunci când se trece de la o activitate la alta, în comparaţie cu ceea ce are loc în cazul unei

simple apelări de procedură.

Un caz tipic de asincronism este executarea intrărilor-ieşirilor simultan cu execuţia unui

program. Trebuie să fie asigurată posibilitatea informării programului despre terminarea unui

transfer de informaţii. O primă posibilitate, care nu necesită utilizarea unor dispozitive

speciale, este cea a aşteptării active, prezentată mai jos.

31. Mecanisme de comutare a contextului

Comutarea contextului unui procesor permite executarea într-o manieră indivizibilă a

următoarelor două operaţii:

trecerea cuvântului de stare într-un amplasament specificat al memoriei,

încărcarea în cuvântul de stare a conţinutului unui alt amplasament specificat

al memoriei.

Aceasta se poate întâmpla doar dacă procesorul se află într-o stare observabilă (de exemplu,

între execuţia a două instrucţiuni) sau de aşteptare. Din aceste considerente noţiunea de "punct de

întrerupere" este sinonim al noţiunii "punct observabil".

Comutarea contextului poate fi necesară din mai multe cauze distincte. Presupunem că

fiecărei cauze i-a fost asociat un număr de ordine. Pot fi întâlnite două scheme de comutare a

contextului.

1) Salvare în amplasamente fixe. Fiecărei cauze (numărul unei cauze fiind i) îi

sunt ataşate în mod constant două amplasamente de memorie adresele cărora le vom nota

prin csp_vechi[i] şi csp_nou[i] (csp semnificând cuvânt de stare program). Comutarea se

produce după cum urmează:

Mp[csp_vechi[i]]:=<cuvânt de stare program>

<cuvânt de stare program>:= Mp[csp_nou[i]]

Page 15: spora

15

În setul de instrucţiuni există o instrucţiune privilegiată schimbă_csp(adr) cu următorul

efect:

<cuvânt de stare program>:= Mp[adr].

2) Salvare într-o stivă. Aici avem acelaşi procedeu în ceea ce constă cuvântul

de stare nou. Însă cuvântul de stare vechi nu este salvat într-un amplasament fix, ci într-o

stivă specială:

ptr :=ptr+1

stiva[ptr] :=<cuvânt de stare program>

<cuvânt de stare program> := Mp[csp_nou[i]]

Instrucţiunea schimbă_csp(adr) este identică celei din 1); există însă şi o instrucţiune

restabileşte_csp, care restabileşte cuvântul de stare a procesorului folosind pentru acesta top-ul

stivei:

<cuvânt de stare program> :=stiva[ptr]

ptr :=ptr-1

Comutarea contextului, descrisă mai sus, este declanşată sub influenţa stării unor indicatori

interni pe care procesorul îi consultă la interpretarea fiecărei instrucţiuni. Conform semnificaţiei

acestor indicatori şi maniera în care ei sunt modificaţi, pot fi evidenţiate trei mecanisme de

comutare, descrise în tabelul de mai jos:

Tabelul 2.1. Mecanisme de comutare a contextului

Denumirea

mecanismului

Cauza Utilizarea

Întrerupere Exterioară

derulării instrucţiunii

curente

Reacţionare la un

eveniment asincron extern

Deviere Legată de

derularea instrucţiunii

curente

Tratarea unei erori

sau situaţii excepţionale

Apelarea

supervizorului

Comutare

explicită

Apelarea unei funcţii

a S.O.

Adesea toate aceste trei denumiri sunt înlocuite cu una singură - întrerupere.

32. Întreruperi

O întrerupere este comutarea contextului procesorului declanşată de o cauză externă

derulării instrucţiunii curente. Fizic, întreruperea înseamnă trimiterea unui semnal procesorului,

acest semnal provocând schimbarea stării unuia dintre indicatorii, consultaţi în cursul executării

fiecărei instrucţiuni. 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 execuţia unui program predefinit. Acesta din urmă este numit

Page 16: spora

16

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, diferenţa fiind legată de modul de tratare, protecţie, informaţiile accesibile, etc.

Nivele de prioritate. Cauzele care duc la necesitatea întreruperii unui procesor sunt

diferite, drept rezultat şi programele predefinite, care tratează întreruperile diferă. Mecanismul

întreruperilor trebuie să poată deosebi aceste cauze. Două scheme de bază sunt utilizate în acest

scop:

Există un indicator unic pentru toate întreruperile şi acestui indicator îi este asociat

un program unic de tratare a întreruperilor. O informaţie suplimentară (codul întreruperii),

care se conţine în cuvântul de stare sau într-un amplasament de memorie, dă posibilitatea de

a deosebi cauzele. Prima obligaţie a programului de tratare a întreruperilor este de a

consulta codul întreruperii pentru a stabili originea acesteia, doar apoi se va trece la tratarea

propriu-zisă.

Fiecărei cauze este ataşat un indicator, se mai spune că fiecare cauză este ataşată

unui nivel de întrerupere. Fiecărui nivel îi corespunde un program distinct de tratare a

întreruperii, activat în mod automat de către mecanismul de comutare a contextului.

Priorităţi şi mascarea întreruperilor. Atunci când există mai multe nivele de întrerupere

este posibilă necesitatea modificării simultane a doi indicatori, legaţi de două cauze diferite.

Conflictul poate fi reglat stabilind o ordine de prioritate în cadrul nivelelor de întrerupere.

Această ordine poate fi fixată odată pentru totdeauna sau modificabilă prin microprogramare.

Adesea este utilă protejarea, contra unor întreruperi anume, a execuţiei unei suite de

instrucţiuni (de exemplu, poate fi interzisă întreruperea unui program de tratare a întreruperii).

Aceasta ar însemna întârzierea comutării contextului, comutare, provocată de sosirea unui

semnal asociat unui nivel oarecare de întrerupere. Se zice atunci, că nivelul este mascat sau

inhibat (întrerupere mascată). Ridicarea inhibării ("demascarea") va autoriza schimbarea

ulterioară a contextului. Informaţiile asociate mascării întreruperilor se află în cuvântul de stare a

procesorului.

Pentru unele nivele de întrerupere efectul sosirii semnalului de întrerupere poate fi suprimat

(nu doar întârziat). Totul se va petrece în acest caz ca şi cum însăşi cauza întreruperii a fost

suprimată: nivelul întreruperii este dezarmat. Un nivel dezarmat poate fi rearmat, adică repus

în serviciu.

Declanşare programată. Pentru unele calculatoare, îndeosebi cele utilizate în controlul

proceselor, există o instrucţiune de declanşare programată care permite modificarea

indicatorului, asociat unui nivel de întrerupere, din interiorul unui program. În acest fel este

posibilă simularea apariţiei unei cauze externe de întrerupere.

Atunci când toate condiţiile necesare pentru ca o întrerupere să fie luată în consideraţie sunt

prezente, nivelul se numeşte activ. Această stare corespunde executării programului de tratare a

întreruperii. Notăm, că această execuţie poate fi suspendată pentru a permite tratarea unei

întreruperi cu o prioritate mai înaltă. Ieşirea din starea activă se face prin achitarea întreruperii.

Page 17: spora

17

Achitarea este realizată folosind instrucţiunea schimbă_csp, care termină tratarea schimbând

contextul.

Operaţiile de armare, dezarmare, mascare, demascare şi declanşare a întreruperilor sunt

totdeauna realizate prin intermediul unor instrucţiuni privilegiate.

Schema unui program de întrerupere. O întrerupere forţează procesorul să reacţioneze la

un eveniment. Executarea programului curent este suspendată, comanda fiind transmisă

programului de tratare a întreruperii. Programul reluat de către procesor după tratarea întreruperii

nu este în mod obligator programul întrerupt (întreruperea putea avea scopul realocarea

procesorului).

33. Devieri şi apelarea supervizorului

O deviere semnalizează o anomalie în derularea unei instrucţiuni, care prohibitează

executarea instrucţiunii. Originile pot fi diverse:

date incorecte, care conduc la imposibilitatea execuţiei corecte a instrucţiunii

(împărţirea la zero, de exemplu),

tentativa executării unei operaţii interzise de mecanismul de protecţie

(violarea protecţiei memoriei, executarea unei instrucţiuni privilegiate în modul program,

etc.),

instrucţiune neexecutabilă (cod neautorizat de operaţie, adresă în afara

memoriei existente, utilizarea unui dispozitiv opţional, care este lipsă în configuraţia dată,

etc.).

Devierile pot fi clasificate, ca şi întreruperile, conform cauzelor care le generează. Efectul

unor cauze poate fi suprimat (de exemplu devierile legate de operaţiile aritmetice, erorile fiind

semnalate doar de valoarea codului condiţiei). Natura unei devieri nu permite aplicarea

noţiunii de mască. 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 instrucţiune chemată să provoace o comutare a contextului procesorului. Acest efect este

analogic apelării unei proceduri, însă modificarea contextului este mai profundă, fiindcă ea

afectează întreg cuvântul de stare şi nu numai contorul ordinal.

Destinaţia unui apel al supervizorului este de a permite apelarea unei proceduri a sistemului

de operare, pretinzând la drepturi mai mari (modul master, întreruperi mascate, drepturi de acces,

etc.), direct din programul utilizatorului. Mecanismul comutării contextului permite asigurarea

protecţiei, impunând condiţiile de intrare procedurii apelate. Ca rezultat:

contextul nou (modul, masca, etc.,) este specificat în noul cuvânt de stare,

amplasat intr-o zonă de memorie inaccesibilă utilizatorilor,

programul de tratare a apelului supervizorului începe cu o secvenţă de

verificare a drepturilor utilizatorului de a executa acest apel şi stabilirea validităţii

parametrilor transmişi.

Tratarea

întreruperii

Salvarea contextului

programului P

Comutarea cuvântului de

stare

Programul întrerupt

P

Tratarea specifică întreruperii, care presupune

determinarea programului Q pentru lansare (poate fi

chiar P sau altul)

Restabilirea contextului programului

Q încărcarea cuvântului de stare a lui

Q

Instrucţiunea schimbă_csp (achitare)

Programul nou Q

Fig.2.4. Schema generală a tratării unei întreruperi

Page 18: spora

18

Parametrii sunt transmişi ca şi în cazul apelului unei proceduri obişnuite. Returul în

programul apelant se face prin restabilirea cuvântului de stare salvat la apelare.

Operaţiile de accesare a fişierelor şi de intrare-ieşire sunt disponibile utilizatorilor sub

forma apelării supervizorului.

34. Exemple de sisteme de întreruperi

Funcţionarea sistemelor de întrerupere este ilustrată prin două exemple reprezentative, unul

pentru un calculator mare, altul pentru calculatoarele personale.

Exemplul 2.6. IBM 370.

Cuvântul de stare (64 biţi) conţine următoarele câmpuri:

<0-7> masca întreruperii <16-31> codul întreruperii

<8-11> cheie de protecţie <32-33> lungimea instrucţiunii

<12> codul caracterelor <34-35> codul condiţiei

<13> masca întreruperii <36-39> suprimarea devierii

<14> 1 - aşteptare, 0 - activ <40-63> contor ordinal

<15> 0 - stăpân, 1 - sclav.

Sistemul de întreruperi are 5 nivele (în ordinea de descreştere a priorităţilor): eroare

hardware, deviere, apelare supervizor, extern şi intrare-ieşire. Fiecărui nivel îi corespunde în

memoria operativă un cuplu de amplasamente rezervate cuvintelor de stare vechi şi nou. Fiecare

nivel conţine mai multe cauze de întrerupere. Pentru a face o deosebire a acestor cauze este

utilizat un cod al întreruperii format din biţii 16 - 31 ai cuvântului de stare. Acest cod este în mod

automat pus la zi în cazul unei întreruperi. De exemplu, pentru o întrerupere de intrare-ieşire el

va conţine adresa canalului şi a perifericului care au provocat întreruperea; pentru o întrerupere

externă acest cod permite să se stabilească originea - ceasul, apel al operatorului, adresare a unui

organ extern, etc. Biţii 0 - 7 şi 13 ai cuvântului de stare permit introducerea măştii întreruperii. Ei

permit mascarea nivelelor de întrerupere externă, eroare hardware şi, selectiv, întreruperile de

intrare-ieşire, care provin de la diferite canale. Biţii 36 - 39 permit inhibarea a 4 cauze de

deviere.

Observăm, că devierile şi a apelările supervizorului sunt tratate ca şi întreruperi particulare.

Exemplul 2.7. IBM PC. Este propus ca exerciţiu.

35. IMPLEMENTAREA MECANISMELOR DE COMUTARE A

CONTEXTULUI

Implementarea mecanismelor descrise mai sus este ilustrată printr-o serie de exemple,

legate de utilizarea lor.(intrebarea 6)

Vom preciza notaţia utilizată în schemele programelor:

conţinutul unui cuvânt de stare este reprezentat prin notaţia <activitate, mod,

mascare, contor ordinal>. Primele trei câmpuri pot lua, respectiv, valorile: aşteptare/activ,

master/slave, mascat/demascat. Dacă csp desemnează un cuvânt de stare, câmpurile sale

vor fi desemnate de csp.act, csp.mod, csp.masc şi csp.co.

Page 19: spora

19

operatorul adr aplicat unui identificator de variabilă sau de procedură,

desemnează adresa amplasamentului unde se află variabila sau prima instrucţiune a

procedurii,

notaţia Mp[adr] desemnează conţinutul amplasamentului cu adresa adr.

Notaţiile svc_vechi, dev_vechi, intr_x_vechi, svc_nou, dev_nou, intr_x_nou

desemnează amplasamentele unde sunt plasate şi de unde sunt încărcate cuvintele de stare.

Vom mai presupune că

apelarea supervizorului este de forma SVC <cod>, unde <cod> reprezintă un

număr care permite identificarea funcţiei cerute,

un indicator <cauză> permite stabilirea cauzei care provoacă o deviere.

Schemele prezentate conţin un program de iniţializare, executat la prima încărcare a

sistemului. Funcţia acestui program este de a iniţializa cuvântul de stare asociat tratării

întreruperilor, devierilor şi apelurilor supervizorului.

36. Utilizarea devierilor şi apelării supervizorului

Simularea instrucţiunilor lipsă. Unele instrucţiuni din setul de bază de instrucţiuni ale

procesorului pot fi opţionale şi, deci, pot lipsi în unele configuraţii ale calculatorului. Tentativa

executării unei instrucţiuni opţionale lipsă generează o drivere de tipul instrucţiune inexistentă.

Mecanismul devierilor poate fi utilizat pentru a realiza prin program instrucţiunea inexistentă în

setul de bază. De exemplu, pentru o configuraţie în care operaţiile aritmetice în virgulă mobilă

nu sunt disponibile ele pot fi simulate prin apelarea procedurilor corespunzătoare. Aceste

proceduri trebuie executate în mod slave pentru a permite tratarea explicită a erorilor: ele sunt

apelate prin încărcarea unui cuvânt de stare. O adresă de retur trebuie să fie pregătită de către

programul de tratare a devierii în top-ul stivei pentru a asigura returul la instrucţiunea care

urmează instrucţiunii de operaţie aritmetică simulată.

Realizarea prin program:

procedura iniţializare;

dev_nou:=<activ,master,mascat, adr tratare_deviere>;

csp[ADD_FL]:= <activ,slave,demascat, adr ADD_FL>;

……

csp [DIV_FL]:= <activ,slave,demascat, adr DIV_FL>;

procedura tratare deviere;

begin

save(zonă);

case cauză of

……

instrucţiune inexistentă:

cod_op:=Mp[dev_vechi.co].cod_operaţie;

case cod_op of

……

Page 20: spora

20

ADD_FL: determinarea operanzilor;

introdu_în_stivă(stivă_utilizator,dev_vechi.co+1);

încarcă_csp(csp[ADD_FL])

……

else -- caz de eroare

<tratarea erorii>

end;

end;

restabilire(zonă);

încarcă_csp(dev_vechi)

end

Operanzii vor fi determinaţi prin analiza conţinutului instrucţiunii, care conţine adresele lor;

returul rezultatelor utilizează convenţiile proprii instrucţiunii în cauză (plasarea într-un registru,

etc.).

Măsurarea capacităţii memoriei. Un sistem de operare presupune a fi utilizat pentru

diverse configuraţii ale calculatorului. Capacitatea memoriei, numărul şi natura dispozitivelor

periferice, etc., pot fi diferite. Sistemul de operare trebuie să se adapteze configuraţiei concrete,

ca şi condiţiilor particulare de utilizare (număr de utilizatori, priorităţi, etc.). Crearea unei

asemenea versiuni specifice se numeşte generarea sistemului de operare. Pentru a reduce

frecvenţa generărilor S.O. unii parametri de configurare pot fi determinaţi în mod automat la

iniţializare.

Astfel, poate fi determinată capacitatea memoriei operative utilizând o deviere pentru

adresa amplasamentului de memorie inexistent. Memoria constă dintr-un număr nbloc de

blocuri (care trebuie determinat), fiecare bloc conţinând p cuvinte. Un program executat la

iniţializarea sistemului încearcă să acceseze ciclic primul cuvânt al fiecărui bloc; tentativa de

accesare a primului bloc inexistent în configuraţia curentă provoacă, prin deviere, părăsirea

buclei. Numărul de blocuri este egal cu numărul primului bloc neimplantat (blocurile fiind

numerotate începând cu 0).

Realizarea prin program:

program principal:

begin

dev_nou:= <activ,master,mascat, adr măsurare>;

i:=1;

ciclu

<accesare cuvânt cu adresa i.p>;

i:=i+1;

endciclu;

ieşire ciclu: nbloc:=i;

Page 21: spora

21

dev_nou := <activ,master,mascat, adr tratare_deviere>;

end

procedura măsurare; -- apelare prin deviere

if cauză = adresă în afara memoriei then

csplucrare:= <activ,master,mascat, adr ieşire ciclu>;

încarcă_csp(csplucrare)

endif

La ieşirea din programul de măsurare a capacităţii memoriei se va restabili tratarea normală

a devierilor (procedura tratare_deviere).

Gestionarea devierilor de către utilizatorul sistemului. Reacţia standard la o deviere care

are loc în timpul execuţiei unui program utilizator este apelarea unei proceduri de sistem, care

provoacă emiterea unui mesaj de eroare, oprirea programului curent şi trecerea la programul

următor.

Este de dorit ca fiecare utilizator să aibă posibilitatea să asocieze fiecărei cauze distincte de

deviere i o procedură proprie, tratarea căreia ar înlocui reacţia standard. Pentru a evita o buclă

infinită, o deviere din aceeaşi 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 următor se va apela o procedură a sistemului de operare, apel

realizat prin încărcarea unui cuvânt de stare, numit schimbare.

Realizarea prin program:

const ndev=<numărul de cauze de deviere>;

var C: array[0..ndev-1] of boolean;

adrtratare: array[0..ndev-1] of adresă;

procedura iniţializare;

begin

svc_nou:=<activ,master,mascat, adr tratare_svc >;

for i:=0 to ndev-1 do -- tratare standard

C[i]:=false;

endfor;

dev_nou:=<activ,master,mascat, adr tratare_dev >;

end

procedura tratare_svc;

begin

save(zonă);

case cod of

……

Page 22: spora

22

asociere_deviere: -- parametrii i, proc

C[i]:=true;

adrtratare[i]:=adr proc;

restabilire(zonă);

încarcă_csp(svc_vechi)

……

endcase

end

procedura tratare_dev(i);

begin

save(zonă);

if C[i] then

C[i]:=false; -- restabilire tratare standard

introdu_în_stivă(stivă_utilizator,dev_vechi.co); -- pentru retur

dev_vechi.co:= adrtratare[i];

restabilire(zonă);

încarcă_csp(dev_vechi);

else

<tratare standard[i]>;

încarcă_csp(schimbare); -- programul următor

endif

end

Programul de tratare a devierii, specificat de către utilizator se va executa în modul slave,

iar returul se va face cu ajutorul mecanismului standard de retur dintr-o procedură, deoarece

adresa de retur a fost pusă în vârful stivei de execuţie.

37. Exemple de utilizare a întreruperilor

Principala utilizare a întreruperilor este măsurarea timpului şi administrarea operaţiilor de

intrare-ieşire. Prezentăm mai jos câteva exemple de utilizare a ceasului calculatorului.

Un ceas de calculator este realizat cu ajutorul unui oscilator cu cuarţ, care emite impulsuri

periodice. Perioada de emitere, de obicei poate fi aleasă dintr-o plajă de valori prestabilită, de

exemplu de la 0.1 până la 100 microsecunde. Aceste impulsuri sunt utilizate pentru a decrementa

valoarea unui contor, conţinut într-un registru special sau într-un cuvânt de memorie, rezervat

acestui scop. Când acest contor trece prin zero este declanşată o întrerupere, numită întrerupere

de ceas, care corespunde unui nivel rezervat acestui efect.

Pentru aplicaţiile care urmează vom presupune, că fiecare impuls decrementează cu 1

conţinutul unei locaţiuni de memorie, notat ceas.

Page 23: spora

23

Limitarea timpului de execuţie a unei proceduri. Este necesar să fie executată o procedură

p astfel, încât dacă după un interval de timp prestabilit q, numit timeout, executarea nu se va

termina, ea va fi întreruptă şi o procedură specificată tratare_eroare este apelată.

Realizarea prin program:

procedura iniţializare;

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; -- salvare pentru retur

csplucrare:= <activ,slave,demascat,adr p>;

csperoare:= <activ,slave,demascat,adr tratare_eroare>;

armare(intr_ceas);

restabileşte(zonă);

încarcă_csp(csplucrare);

retur: -- datorat terminării procedurii p

dezarmare(intr_ceas);

încarcă_csp(cspretur);

endcase

procedura intr_ceas; -- expirarea timpului limită

dezarmare(intr_ceas);

încarcă_csp(csperoare);

Primul eveniment, care va avea loc (expirarea timpului q, rezervat executării, sau returul din

p), dezarmează ceasul şi activează procedura adecvată pasându-i contextul curent. Returul din p

trebuie să se facă prin apelarea supervizorului şi nu printr-o instrucţiune obişnuită de retur. La fel

se va proceda şi cu returul din tratare_eroare, dacă se cere revenirea la contextul apelării iniţiale

a procedurii p.

Culegerea unor date de măsurare. Un calculator are obligaţiunea să preia periodic datele

unor măsurări legate de o instalaţie industrială. Perioada ceasului este de 5 μs. Datele trebuie

culese fiecare 100 ms (perioada de eşantionare). Deoarece timpul necesar culegerii datelor este

cu mult inferior perioadei de eşantionare, calculatorul poate executa alte lucrări în regim de fond.

Page 24: spora

24

Realizarea prin program:

const q = 20000 -- 100ms/5μs

procedura iniţializare;

begin

intr_ceas_nou:=<activ,master,mascat,adr intr_ceas>;

csplucrare:= <activ,slave,demascat,adr fond>;

cspmăsurare:= <activ,slave,demascat,adr măsurare>;

ceas:=q;

încarcă_csp(cspdev)

end

procedura intr_ceas;

begin

save(zonă); salvarea contextului de fond

cspsave:=intr_ceas_vechi; salvarea cuvântului de stare pentru fundal

ceas:=q;

încarcă_csp(cspmăsurare) programul de culegere a datelor

end

Programul de măsurare trebuie să se termine printr-o apelare a supervizorului SVC retur

efectul căreia este de a restabili contextul lucrului în fond. Acest apel execută secvenţa:

restabileşte (zonă);

încarcă_csp(cspsave);

Remarcă. Putem include procedura măsurare direct în programul de tratare a întreruperii,

care ar fi avut în forma

save(zonă);

ceas:=q;

măsurare;

restabileşte(zonă);

încarcă_csp(intr_ceas_vechi)

Dar în acest caz programul de măsurare va trebui să fie executat în modul master şi

întreruperile să fie mascate, ceea ce nu ar permite modificarea sau înlocuirea lui de către un

utilizator neprivilegiat. Această remarcă ilustrează un principiu general, care cere îndeplinirea

independentă (decuplată) a programelor de tratare a întreruperilor (secvenţe de scurtă durată,

executate cu privilegii înalte) şi programele activate de către procedurile de tratare a

întreruperilor şi apelate prin încărcarea unui cuvânt de stare (tratare primară şi secundară a

întreruperii).

Administrarea lucrărilor în timp partajat. O mulţime de programe sau lucrări trebuiesc

executate pe un calculator, utilizând procesorul în regim de partajare a timpului: procesorul este

alocat succesiv lucrărilor într-o ordine prestabilită, pentru tranşe de timp de durată fixă q (cuanta

Page 25: spora

25

de timp). Dacă o lucrare este încheiată înainte de expirarea cuantei q, procesorul este imediat

alocat lucrării următoare.

Lucrările sunt numerotate de la 0 la n-1. Este definită o zonă de amplasare a cuvântului de

stare a procesorului csp[i] pentru fiecare lucrare i şi o altă zonă reg[i] pentru registrele acesteia.

Aceste zone permit salvarea contextului procesorului de fiecare dată când o lucrare este

întreruptă pentru a permite reluarea ulterioară a lucrării întrerupte.

Realizarea prin program:

Pentru început, presupunem că lucrările nu se vor termina niciodată. Vom utiliza un fir

circular de lucrări, notat fir_lucr şi gestionat de trei proceduri intrare, ieşire şi urm.

procedura iniţializare;

begin

for i:=0 to n-1 do

csp[i] := <activ,slave,demascat,adr lucrare[i]>;

intrare(i, fir_lucr);

endfor

intr_ceas_nou:=<activ,master,mascat,adr intr_ceas>;

svc_nou:=<activ,master,mascat,adr trattare_svc>;

lucr_ales:=0; -- începem cu lucrarea 0

încarcă_csp(csp[lucr_ales]);

end

procedura intr_ceas;

begin

csp[lucr_ales]:=intr_ceas_vechi;

save_registre(reg[lucr_ales]);

lucr_ales:=urm(lucr_ales);

ceas:=q;

încarcă_registre(reg[lucr_ales]);

încarcă_csp(csp[lucr_ales]);

end

Pentru a lua în consideraţie terminarea lucrărilor, fiecare lucrare trebuie să înştiinţeze

sistemul atunci când execuţia sa a luat sfârşit printr-un apel al supervizorului SVC end după cum

este prezentat mai jos.

procedura tratare_svc;

case cod of

term:

suc:=urm(lucr_ales);

Page 26: spora

26

ieşire(lucr_ales, fir_lucr);

lucr_ales:=suc;

ceas:=q;

încarcă_registre(reg[lucr_ales]);

încarcă_csp(csp[lucr_ales]);

endcase

Am presupus că firul de lucrări nu va deveni niciodată vid. În practică aceasta poate fi

obţinut prin trecerea la o lucrare de fond, care poate eventual fi redusă la o buclă.

Concluzii

Exemplele precedente ilustrează modurile elementare de comunicare dintre programele unui

sistem de operare şi mediul exterior. Programele sistemului sunt activate:

1) fie de către un program al utilizatorului, care semnalează o anomalie (deviere)

sau cere achitarea unui serviciu (apelarea supervizorului),

2) fie de către un dispozitiv extern (ceas, proces comandat, organ periferic sau

linie de comunicaţii), care semnalează producerea unui eveniment şi care cere o reacţie

imediată a sistemului.

Ca şi rezultat putem afirma că un sistem de operare este pilotat de evenimente (event-

driven, eng.). Notăm de asemenea, că comunicaţia internă între programele unui sistem foloseşte

apelarea supervizorului dacă un anumit tip de protecţie trebuie să fie activat (program executat

în modul slave, de exemplu) şi apelarea unei proceduri obişnuite în caz contrar. O secvenţă de

execuţie a unui program de sistem se termină prin încărcarea unui cuvânt de stare a procesorului

care permite controlul total al contextului restabilit.

38. PROGRAMAREA OPERAŢIILOR DE INTRARE-IEŞIRE

Prin noţiunea de intrare-ieşire (prescurtat I/E; eng. input/output, I/O; fr. entrée-sortie, E/S)

numim orice transfer de informaţii din sau spre nucleul calculatorului. Operaţiile de I/E

semnifică:

transferurile de informaţii dintre diferite nivele ierarhice ale memoriei,

transferurile de informaţii din sau spre mediul exterior (organe periferice

locale sau la distanţă, captoare sau dispozitive de acţionare, alte calculatoare, etc.).

39. Organizarea general

Periferice, controlere, canale

Un organ de intrare-ieşire este un dispozitiv capabil să transfere informaţii între procesorul

sau memoria calculatorului şi un suport extern de informaţie. Acest transfer este comandat de

către procesorul central. În cel mai simplu caz, o instrucţiune specială a procesorului permite

transferarea informaţiei între suportul extern şi un registru al procesorului, care va fi deci ocupat

pe toată perioadă transferului informaţiei. Odată cu evoluţia calculatoarelor, în scopul unei mai

bune utilizări a procesorului s-a ajuns la necesitatea acordării unei autonomii organelor de

intrare-ieşire încredinţându-le funcţii tot mai complicate de înlănţuire şi comandă, procesorului

central lăsându-i-se doar iniţiativa de lansare şi de control a operaţiilor. Din considerente

Page 27: spora

27

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.

Câteva scheme de organizare a perifericelor sunt prezentate în fig.2.5. Schema (c) este

proprie unui calculator de putere mare, (a) şi (b) corespund configuraţiilor calculatoarelor de

putere mai mică. Precizăm funcţiile organelor reprezentate în această figură.

1) Un canal (sau unitate de schimb) este un procesor specializat în operaţiile de

intrare-ieşire. El poate fi lansat doar de un procesor central, nu posedă întreruperi, dar

poate întrerupe un procesor central. Setul de instrucţiuni ale canalului îi permite să

acţioneze controlerele şi perifericele, care-i sunt conectate. Mini- şi microcalculatoarele

pot poseda organe, numite Unităţi de acces direct la memorie (ADM), care sunt nişte

canale simplificate.

2) Un contróler este un dispozitiv de comandă adaptat la un tip concret de

echipament periferic. Autonomia sa este limitată de operaţii foarte elementare. Destinaţia

principală a unui controler este de a permite conectarea a mai multor periferice de acelaşi

tip la un singur controler. Un singur dispozitiv periferic poate transmite informaţii prin

intermediul controlerului la un moment de timp dat. În acelaşi timp, este posibilă

executarea simultană a unor operaţii pe alte periferice, operaţii care nu implică transferul

de informaţii (rebobinarea unei bande magnetice, deplasarea braţului unui disc, etc.).

Partajarea funcţiilor între periferic şi controler depinde de tipul perifericului. De obicei,

funcţiile logice (înlănţuirea şi sincronizarea operaţiilor, emiterea unor semnale în caz de

accident sau terminarea normală a execuţiei) sunt încredinţate controlerului, iar funcţiile

fizice (transferul propriu-zis) - perifericului. În programarea intrărilor-ieşirilor 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 informaţii din sau spre un

suport extern. Controlerul este legat de periferic printr-o interfaţă, care conţine un set de

funcţii (intrare, ieşire, semnalizări de comandă şi de accident) şi o linie de comunicaţie,

care serveşte la transferul informaţiilor.

UC

M

ADM

Magistrală

Cp

p

Cp

p

UC

M

Cp

p

Cp

p

Magistrală

(a) (b)

M

C C

Magistrală

UC UC

UC : unitate centrală

Page 28: spora

28

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 (unităţi centrale sau canale) de a accesa simultan memoria operativă poate genera

conflicte. Conflictele sunt reglate de către dispozitivul hardware de accesare, care impune o

ordine de acces conform unor priorităţi prestabilite. Canalele au prioritate faţă de unităţile

centrale, deoarece ele trebuie să reacţioneze cât se poate de rapid la evenimentele externe.

2.4.1.2. Adresarea dispozitivelor periferice

Diferite organe sunt desemnate, la fiecare nivel, printr-o adresă care permite să

evidenţiem:

canale legate de memorie,

controlere ataşate fiecărui canal,

dispozitive periferice ataşate fiecărui controler.

La un nivel anume adresa este un simplu număr de ordine. Un periferic este

desemnat printr-o adresă compusă

<numărul canalului, numărul controlerului, numărul dispozitivului

periferic>.

Un controler poate fi conectat la mai multe canale, iar un periferic la mai multe controlere,

care vor fi, obligator, de acelaşi tip. Astfel, un periferic are mai multe căi de acces la memorie

(doar una singură poate fi activă la un moment de timp dat) şi poate fi desemnat prin mai multe

adrese (fig.2.6).

Page 29: spora

29

Această organizare permite ameliorarea performanţelor şi disponibilităţii sistemului.

Existenţa mai multor căi de acces la un periferic diminuează riscul unor indisponibilităţi din

cauza saturaţiei sau ieşirii din funcţiune a unui canal sau controler.

În cazul unor calculatoare, cum ar fi de exemplu DEC, adresarea perifericelor utilizează

amplasamente de memorie rezervate, care sunt asociate cuvântului de stare sau registrului de

date a unui controler specificat. Accesarea cuvântului de stare sau a registrului de date este

realizată prin intermediul instrucţiunilor obişnuite de accesare a memoriei. Această schemă

simplifică desemnarea perifericelor şi programarea intrărilor-ieşirilor.

40. Metode de comandă a perifericelor

Programul, care controlează funcţionarea elementară a unui dispozitiv periferic se numeşte

driver. Driverul gestionează în mod direct interfaţa controlerului perifericului, tratează

întreruperile generate de acesta, detectează şi tratează cazurile de eroare. El este, de obicei,

invizibil unui utilizator obişnuit al sistemului, care apelează funcţii de intrare-ieşire prin

intermediul unor servicii de înalt nivel, realizate prin apelări ale supervizorului. Vom prezenta

mai jos modurile principale de control ale perifericelor şi primitivele elementare de intrare-ieşire.

Intrări-ieşiri sincrone

În acest caz nu există nici un fel de paralelism între procesare şi transferul informaţiilor.

Procesorul este ocupat pentru toată durata transferului.

Schema care urmează nu descrie doar un caz particular, ci este reprezentativă pentru

organizarea intrărilor-ieşirilor sincrone pentru mai multe tipuri de calculatoare.

1) Specificarea mecanismului

11

01, 10

00

1

0

1

0

1

0

1

0

1

0

1

0

Canal

Canal

Controler

Controler

Controler p

p

p

p

p

001

000

111

011

101

010

100

Fig.2.6. Adresarea perifericelor

Page 30: spora

30

Operaţia de bază constă în transferarea unor informaţii elementare de volum fix între un

amplasament de memorie şi un dispozitiv periferic. Presupunem că volumul informaţiei

transmise, care depinde de perifericul considerat, este un octet. Starea ansamblului controler-

periferic este definită printr-un cuvânt de stare, aflat în controler. Acest cuvânt de stare conţine o

mulţime de indicatori booleeni, dintre care doar 3 ne vor interesa aici:

preg : perifericul este pregătit (gata) de funcţionare, detaliile legate de

stabilirea indicatorului depind de periferic,

term : transferul este terminat; perifericul este gata să transfere un nou

caracter,

err : în cursul transferului a avut loc o eroare; natura ei este

precizată de un cod care face parte din cuvântul de stare.

Controlerul este comandat de unitatea centrală cu ajutorul a trei instrucţiuni de intrare-

ieşire, efectul cărora este descris mai jos:

IN(adr_mem, adr_perif) : cerere de transfer tip intoducere a

unui octet,

OUT(adr_mem, adr_perif) : cerere de transfer tip extragere

a unui octet,

TEST(adr_perif) : copie cuvântul de stare într-un registru cu

scopul de a consulta indicatorii.

Prin adr_mem şi adr_perif sunt desemnate adresele amplasamentului memoriei şi

perifericului.

2) Programul driver-ului

Fie că vrem să extragem o secvenţă de n caractere care se află într-un masiv T[0..n-1].

Caracterul T[i], dacă i>0, poate fi extras doar dacă a fost transferat T[i-1]. Pentru a verifica

această condiţie se testează iterativ (aşteptare activă) un indicator term.

iniţializare : term:=false;

TEST(adr_perif);

if nonpreg then

<tratare eroare>

endif;

Page 31: spora

31

for i:=0 to n-1 do

OUT(adr T[i],adr_perif);

ciclu : TEST(adr_perif);

if err then

<tratare eroare>

endif;

if nonterm then goto ciclu

endif;

endfor

Intrările-ieşirile sincrone sunt folosite la microprocesoarele cele mai simple sau atunci

când procesorul nu poate fi exploatat în mod util în timpul transferului (înregistrări de măsurare,

încărcarea iniţială a unui sistem).

Intrări-ieşiri asincrone cu întreruperi

1) Specificarea mecanismului.

Terminarea procesului de transferare a caracterului T[i] este semnalizată printr-o

întrerupere. Dacă acest caracter nu este ultimul (i<n-1), următorul caracter poate fi transmis.

Procesul este declanşat de transferul primului caracter. Acest transfer este cerut de către

programul principal prin intermediul unui apel a supervizorului (SVC intrare sau ieşire), care are

drept parametri:

adresa perifericului,

numărul de caractere care vor fi transferate,

adresa de origine sau de destinaţie a primului caracter,

un boolean term, valoarea TRUE a căruia semnalizează sfârşitul transferului.

Programul principal programul de

tratare a întreruperii

term:=FALSE (la părăsirea lui T[i])

SVC i:=0;

Page 32: spora

32

ieşire OUT(adr T[i], adr_perif);

save context;

TEST(adr_perif);

… if err then

<tratare eroare>

else

if i<n-1 then

<tratare paralelă> i:=i+1;

OUT(adr T[i], adr_perif)

… else

term:=TRUE

if term then endif

… endif;

<restabilire context>

2.4.2.3. Intrări-ieşiri programate pe canal sau acces direct la memorie

41. Intrări-ieşiri buferizate în memorie

Specificarea problemei

Diferenţa considerabilă dintre viteza de lucru a unităţii centrale şi cea a organelor

periferice impune "buferizarea" intrărilor-ieşirilor, adică introducerea unei zone de memorie-

tampon între periferic şi programul utilizatorului. Scopul este de a reduce timpul de inactivitate a

unităţii centrale, dezlegând funcţionarea acesteia de periferice. Programul utilizatorului va

transfera informaţiile din sau spre zona-tampon, iar această zonă-tampon va servi, în mod

paralel, drept sursă sau destinaţie la schimbul de date cu perifericul. Dezlegarea unităţii centrale

de periferic este cu atât mai bine realizată cu cât este mai mare capacitatea zonei-tampon.

Adesea, pentru a nu supraîncărca memoria principală, zona-tampon este situată pe discul fix.

Pentru descrierea modelului sunt necesare următoarele specificaţii:

schimburile de informaţii cu perifericele se va face prin înregistrări de

lungime fixă,

Page 33: spora

33

zona-tampon este de volum fix egal cu N înregistrări,

pentru un program utilizator, schimbul de informaţii cu zona-tampon trebuie

să simuleze schimbul cu perifericul, drept consecinţă, ordinea de depozitare sau de

extragere a informaţiilor trebuie să fie bine stabilită şi nici o înregistrare să nu fie pierdută,

aşteptările inutile trebuie reduse la minimum, atât în cazul unităţii centrale,

cât şi a perifericului,

capacitatea suporturilor nu este limitată: în cazul unei operaţii de citire

organul de intrare va fi totdeauna alimentat; în cazul unei operaţii de scriere, organul de

ieşire poate accepta întotdeauna o înregistrare,

transferul se va efectua fără eroare.

Descrierea algoritmilor

1) Citire

Un program de citire este o procedură citire(înregistrare), care prezintă drept rezultat

valoarea înregistrării citite. Această procedură, realizată printr-o apelare a supervizorului, are ca

efect citirea din zona-tampon a înregistrării următoare. Citirea este posibilă doar dacă zona-

tampon conţine cel puţin o înregistrare, care nu a fost încă citită. În caz contrar, activitatea

apelantă trece în starea de aşteptare. În ambele cazuri, continuitatea alimentării zonei-tampon

este asigurată de citirea unei înregistrări de la perifericul de intrare, dacă un transfer nu are deja

loc.

Terminarea transferului unei înregistrări în zona-tampon provoacă o întrerupere. Pentru a

menţine perifericul în stare activă, programul de tratare asociat acestei întreruperi trebuie să

relanseze transferul următor, dacă mai există loc în zona-tampon. Plus la aceasta, dacă activitatea

apelantă era în aşteptarea sosirii unei înregistrări, ea trebuie relansată.

Acest mod de funcţionare poate fi schematic prezentat conform schemei programului de

mai jos.

periferic de

intrare

programul

utilizator citire (înreg)

Zonă-tampon cu N

locaţiuni

Page 34: spora

34

procedura citire(înreg) tratare

întrerupere

(apelare supervizor)

if tamponul_nu este_vid then if

tamponul_nu este_plin then

extragere(înreg, tampon);

lansare_transfer;

lansare_transfer în caz de necesitate; if

aşteptare then // aşteptare pentru citire

else reluare citire

lansare_transfer în caz de necesitate; endif

aşteptare

endif

În acest program "în caz de necesitate" semnifică "dacă un transfer nu este deja în curs".

Sistemul este iniţializat de citirea primei înregistrări, care provoacă transferuri succesive până la

umplerea zonei-tampon.

2) Scriere

Schema care corespunde unei scrieri se obţine din precedenta, înlocuind după cum

urmează:

citire prin scriere

extragere prin introducere

tampon_vid prin tampon_plin

tampon_plin prin tampon_vid

periferic

de ieşire

programul

utilizator scriere (înreg)

Zonă-tampon cu N

locaţiuni

Page 35: spora

35

procedura scriere(înreg) tratare

întrerupere

(apelare supervizor)

if tamponul_nu este_plin then if

tamponul_nu este_vid then

introducere(înreg, tampon);

lansare_transfer;

lansare_transfer în caz de necesitate; if

aşteptare then

else reluare scriere

lansare_transfer în caz de necesitate; endif

aşteptare

endif

3) Programe

Programele sunt o transcriere a schemelor de mai sus. Zona-tampon este un fir de

aşteptare, gestionat circular cu ajutorul a doi pointeri: tcitire (top-ul FA) - indică următoarea

înregistrare care urmează a fi preluată, qcitire (coada FA) - indică amplasamentul unde se va

introduce următoarea înregistrare. Funcţia suc realizează înlănţuirea amplasamentelor; o realizare

simplă pentru o zonă-tampon secvenţială, care are N înregistrări a câte L amplasamente este de

forma:

suc(ptr) = (ptr + L) mod (L.N)

Vom presupune, că activitatea care cere operaţia citire este unica care va utiliza

procesorul; trecerea acesteia în starea de aşteptare se va realiza trecând în starea de aşteptare

procesorul. Această soluţie este impracticabilă în cazul unor activităţi multiple (este necesar de a

relansa o altă activitate), dar o vom accepta din motive de simplitate.

Mai subliniem că transferul este comandat de un canal sau un ADM, fără a detalia

programul respectiv, pregătit de obicei anticipat; numai valorile parametrilor se vor schimba de

Page 36: spora

36

la o execuţie la alta. Procedurile lansare_citire şi lansare_imprimare realizează pregătirea

programului şi lansarea transferului.

Variabil

e

Semnificaţie Valoare iniţială

L lungimea unei casete

(înregistrări)

const.

Ncitire numărul de casete a zonei-

tampon

const

nvcitire numărul de casete vide Ncitire

citire_a

ctiv

indicator al activităţii

perifericului de intrare

false

tcitire,

qcitire

pointeri top şi coadă 0, 0

suc() pointer spre caseta următoare …

citire(în

reg)

tratare_întrerupere_

perif_de_intrare

save(zonă_svc); save(zonă_întrerupere);

început: qcitire:=suc(qcitire);

if nvcitir<Ncitire then nvcitire:=nvcitire-

1;

periferic

de intrare

programul

utilizator (SVC) citire (înreg)

Zonă-

tampon

qcitire tcitire

Page 37: spora

37

înreg:=tampon[tcitire]; if nvcitire>0 then

tcitire:=suc(tcitire);

lansare_perif_de_intrare(qcitire)

nvcitire:=nvcitire+1; else

if non citire_activ then

citire_activ:=false

citire_activ:=true; endif;

lansare_perif_de_intrare(qcitire) if

aşteptare_citire then

endif întrerupere_veche.act:=activ;

else aşteptare_citire:=false

if non citire_activ then endif;

citire_activ:=true;

restabilire(zonă_întrerupere);

lansare_perif_de_intrare(qcitire)

încărcare_csp(întrerupere_veche);

endif;

csplucrare:=<aşteptare,slave,demascat, adr început>;

lansare_perif_de_intrare(qcitire)

aşteptare_citire:=true; elaborare prog.canal:

încărcare_csp(csplucrare); <sens=citire

endif; adr.memorie=adr tampon[qcitire]

restabilire(zonă_svc); contor_octeţi=L>

încărcare_csp(svc_vechi); SIO

<prog=prog.canal

perif= perif_de_intrare>

Page 38: spora

38

Execuţia programelor de mai sus ne impun să facem o remarcă foarte importantă. Trebuie

să notăm, că executarea tratării întreruperii este declanşată de sfârşitul transferului fizic al unei

înregistrări, activitate, care are loc paralel cu executarea programului primitivei citire(înreg) pe

procesor. Drept rezultat, este posibil ca întreruperea să survină într-un punct oarecare

(observabil) al executării acestei primitive, ceea ce va însemna intercalarea executării

programului de tratare a întreruperii între două puncte oarecare ale programului citire(înreg).

Consecinţele pot fi catastrofale, cum ne arată exemplul următor.

Să considerăm instrucţiunea a doua

if non citire_activ then

citire_activ:=true;

lansare_perif_de_intrare(qcitire)

endif

din programul citire(înreg). Ea se descompune în următoarele instrucţiuni elementare:

(a) load R, citire_activ

(b) jifz R, urm -- ramificare dacă true

(c) …

urm: …

<aşteptare>

Presupunem că întreruperea soseşte între instrucţiunile (a) şi (b), valoarea citită în R de (a)

este true; programul de tratare a întreruperii pune citire_activ în false. După prelucrarea

întreruperii, instrucţiunea (b) este executată cu R având valoarea true şi activitatea apelantă trece

în starea de aşteptare în care rămâne un timp indefinit, deoarece perifericul nu a fost relansat. Pot

exista şi alte cazuri de funcţionare incorectă, legată de momentul sosirii unei întreruperi.

Putem afirma, că validitatea variabilelor comune (de ex. citire_activ, nvcitire etc.,) nu

poate fi garantată dacă autorizăm sosirea întreruperilor de terminare a operaţiilor de intrare-ieşire

în orice moment de timp. Apelarea supervizorului pentru a realiza secvenţa de cod citire_înreg

trebuie executată cu întreruperile de intrare-ieşire mascate. Situaţia dată este cunoscută sub

numele de excludere mutuală şi este o consecinţă a execuţiei activităţilor asincrone.

Programele pentru un periferic de ieşire (imprimare, de ex.) sunt analogice. Remarca

despre mascarea întreruperilor rămâne valabilă.

Page 39: spora

39

Variabil

e

Semnificaţie Valoare iniţială

L lungimea unei casete

(înregistrări)

const.

Nimp numărul de casete a zonei-

tampon

const

nvimp numărul de casete vide Nimp

imp_act

iv

indicator al activităţii

perifericului de intrare

false

timp,

qimp

pointeri top şi coadă 0, 0

suc() pointer spre caseta următoare …

scriere(î

nreg)

tratare_întrerupere_

imp

save(zonă_svc); save(zonă_întrerupere);

început: qimp:=suc(qimp);

if nvimp>0 then nvimp:=nvimp+1;

imprimant

ă

programul

utilizator (SVC) scriere (înreg)

Zonă-

tampon

timp qimp

Page 40: spora

40

tampon[timp]:= înreg; if nvimp<Nimp

then

timp:=suc(timp); lansare_imp(qimp)

nvimp:=nvimp-1; else

if non imp_activ then

imp_activ:=false

imp_activ:=true; endif;

lansare_imp(qimp) if aşteptare_imp then

endif întrerupere_veche.act:=activ;

else aşteptare_imp:=false

if non imp_activ then endif;

imp_activ:=true;

restabilire(zonă_întrerupere);

lansare_imp(qimp)

încărcare_csp(întrerupere_veche);

endif;

csplucrare:= :=<aşteptare,slave,demascat, adr început>; lansare_imp(qimp)

aşteptare_imp:=true; elaborare prog.canal:

încărcare_csp(csplucrare); <sens=ieşire

endif; adr.memorie=adr tampon[qimp]

restabilire(zonă_svc); contor_octeţi=L>

încărcare_csp(svc_vechi); SIO

<prog=prog.canal

perif= imprimantă>

42. Încărcarea iniţială

Page 41: spora

41

Pentru a începe lucrul maşina "goală" trebuie să aibă încărcat în memoria operativă

programul sistemului de operare şi să execute un salt la prima instrucţiune a acestui program.

Aceasta presupune prezenţa în memorie a unui program de citire, care el însuşi trebuie încărcat

în prealabil. La primele calculatoare, un program de câteva instrucţiuni, introdus manual în

memorie cu ajutorul unor comutatoare ale pupitrului de comandă la o adresă fixă, permitea

încărcarea unui program de citire mai elevat capabil să citească versiunea completă a sistemului

de operare. Acest proces era numit încărcare (bootstrapping, eng.).

În calculatoarele contemporane, programul de iniţializare se află permanent într-o

memorie constantă (BIOS). Execuţia acestui program este declanşată odată cu punerea sub

tensiune a calculatorului (autoîncărcare).

43. Gestionarea activităţilor paralele. Exemple introductive

Reluăm exemplul imprimării cu gestionarea unor zone tampon pe disc

Sau

Comanda unui proces industrial

Mai jos sint descrise

44. Administrarea tamponată a intrărilor-ieşirelor

Reluăm exemplul imprimării cu gestionarea unor zone tampon pe disc, descris în capitolul

2. Analiza acestui mod de funcţionare (fig.3.1) pune în evidenţă patru activităţi, care pot avea loc

simultan:

1) primitiva scriere_linie SL (unitatea centrală)

2) scriere pe disc SD (canal 1)

3) citire de pe disc CD (canal 2)

4) imprimare fizică IF (canal 3)

În realitate, citirea şi scrierea pe disc sunt executate pe acelaşi canal, ceea ce poate impune unele restricţii privind simultaneitatea executării lor. Vom ignora aici aceste

restricţii, justificând mai apoi acest mod de procedare.

scriere_linie

(memorie) (memorie)

Fig.3.1. Gestionarea buferizată a unei

imprimante

tm1

td

tm2

SD IF CD

(disc)

SL

Page 42: spora

42

Aceste patru activităţi sunt în mare măsură autonome, or ele sunt executate pe procesoare

distincte, cu programe diferite. Ele nu sunt totuşi independente, deoarece accesează obiecte

comune: două tampoane în memorie, tm1 şi tm2 şi un tampon pe disc, td. Pot fi evidenţiate două

tipuri de condiţii, care trebuie respectate:

Condiţii, care stabilesc posibilitatea existenţei unor activităţi

O înregistrare nu poate fi preluată dintr-un tampon înainte de a nu fi depozitată aici.

Tampoanele au capacităţi limitate; dacă un tampon este ocupat cu înregistrări, care nu au fost

încă preluate, este imposibilă depozitarea fără a pierde informaţii. Acţiunile de depozitare şi

preluare sunt, deci, supuse unor condiţii de posibilitate de existenţă, enumerate mai jos.

Activita

te

Acţiune Condiţie

SL scriere

în tm1

tm1 nu

este plin

SD citire

din tm1

tm1 nu

este vid

SD scriere

în td

td nu este

plin

CD citire

din td

td nu este

vid

CD scriere

în tm2

tm2 nu

este plin

IF citire

din tm2

tm2 nu

este vid

Execuţia activităţilor modifică veridicitatea acestor condiţii: astfel, imprimarea unei linii

pune în TRUE condiţia “tm2 nu este plin”.

O activitate, care nu poate executa o acţiune, deoarece condiţia asociată are valoare FALSE,

trebuie să aştepte, adică execuţia unei acţiuni este retardată până când valoarea logică a condiţiei

Page 43: spora

43

devine TRUE. În capitolul 2 a fost discutată realizarea acestui mecanism de aşteptare şi

continuare cu ajutorul întreruperilor.

Condiţii de validitate a informaţiilor partajate

Dacă vom examina procesul de accesare a tampoanelor, vom descoperi o altă formă de

interacţiune, cauzată de posibilitatea de accesare simultană de către două activităţi a unui

amplsament de memorie. Astfel, dacă SD citeşte conţinutul unei înregistrări din tm1 pe care SL

este în curs de a o modifica, rezultatul acestei citiri riscă să fie incoerent, dacă nu au fost luate

măsuri speciale de precauţie. Problema poate fi rezolvată impunând una din activităţi, aflate în

conflict, să “aştepte” până când cealaltă va termina accesarea.

Concluziile acestei prime analize:

Lucrarea “imprimare tamponată” este realizată prin patru activităţi simultane, în mare

măsură autonome, care cooperează pentru atingerea scopului final.

Executarea corectă a lucrării impune restricţii logice în vederea derulării acestor activităţi.

Aceste restricţii pot conduce la întârzierea execuţiei unei activităţi, care este obligată să aştepte

producerea unui eveniment, provocat de o altă activitate.

45.Comanda unui proces industrial

Să reluăm exemplul din capitolul 1, în care un calculator comandă un reactor

chimic. Considerăm două reactoare identice, R1 şi R2, care funcţionează în paralel. Vom examina

două soluţii posibile:

1) utilizarea a două calculatoare (câte 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. Soluţia a doua

cere stabilirea condiţiilor suplimentare pentru realizarea sa. Implementarea variantei doi impune

verificarea posibilităţii apariţiei unor condiţii suplimentare. Fie P1, P2, D1, D2 segmentele

procedurilor şi datelor pentru comanda celor două reactoare R1 şi R2, memoria principală având

capacitatea necesară pentru păstrarea acestor segmente. Programele P1 şi P2 sunt executate pe

rând de procesor. Raţionând ca şi în capitolul 1, concluzionăm că relaţia 2t<T trebuie să fie

respectată. Dacă acesta va fi cazul, funcţionarea reactoarelor pentru un observator extern pare

identică pentru ambele soluţii. Trebuie, totuşi să subliniem, că soluţia doi impune restricţii mai

severe în ceea ce priveşte performanţele calculatorului (capacitatea memoriei şi viteza de

procesare)

Vom examina mai jos modalităţile de implementare a soluţiei doi.

1) Partajarea procesorului

Page 44: spora

44

Între două execuţii succesive ale lui P1, procesorul este utilizat de P2, ca rezultat starea sa

internă (conţinutul registrelor, cuvântul de stare, contorul ordinal) va fi modificată. Pentru a

permite reluarea lui P1, informaţiile sale trebuiesc salvate la terminarea fiecărei secvenţe de

execuţie şi restabilite la începerea execuţiei următoare. Aceleaşi afirmaţii sunt valabile şi în cazul

executării lui P2.

2) Partajarea programului

Programele P1 şi P2, fiind identice, putem păstra doar o singură copie, să-i zicem P, pentru

economisirea memoriei. Să examinăm condiţiile necesare pentru partajarea programului P:

nu este permisă modificarea codului programului de execuţia sa,

atunci când 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 activităţi independente, eventual simultane, se numeşte program reentrant

(reenterabil). Acest mod de utilizare implică:

invarianţa textului programului în cursul executării sale,

desemnarea uniformă, de către program, a datelor proprii fiecărei activităţi.

Printre altele, dacă activităţile partajează un procesor unic, informaţiile despre starea

acestuia (în particular, cele care servesc la desemnarea datelor) trebuiesc salvate la fiecare

comutare.

Să rezumăm rezultatele celui de-al doilea exemplu.

1. Au fost evidenţiate două activităţi logic independente: comanda reactoarelor

R1 şi R2. Aceste două activităţi pot fi puse pe două maşini distincte fără să existe vre-o

legătură între ele.

2. Considerente de economie pot impune ca aceste activităţi să partajeze resurse

fizice şi resurse program comune. Buna funcţionare a acestei partajări restricţionează

execuţia activităţilor (utilizarea alternativă a procesorului) şi modul de utilizare a

obiectelor partajate (salvarea contextului de executare, reentranţa programelor).

Ca şi concluzie pentru ambele exemple putem evidenţia două momente:

existenţa unor activităţi evolutive, care pot derula simultan,

existenţa unor relaţii între aceste activităţi: cooperare pentru executarea unor

sarcini comune, concurenţă în utilizarea resurselor partajate. Aceste relaţii sunt

determinate de specificaţiile de “bună funcţionare”. Ele se pot traduce în restricţii de

execuţie, care conduc la întârzieri temporare a progresării unei activităţi.

Continuarea acestui capitol are drept scop elaborarea unui suport formal pentru aceste

noţiuni, introducând conceptele de proces şi sincronizare şi descriind modalităţile lor de

utilizare în cadrul unui sistem informatic.

46.Noţiune de proces secvenţial

Page 45: spora

45

Noţiunea de proces este mai întâi introdusă într-un mod concret pentru cazul unui

calculator care conţine un procesor unic şi o memorie adresabilă. Vom trece mai apoi la

definiţia abstractă a unui proces independent de suportul său fizic, ceea ce ne va permite

introducerea problemei sincronizării.

47.Proces unic. Context

Noţiunea de proces pune la dispoziţie un model pentru reprezentarea unei activităţi, care

rezultă din executarea unui program pe calculator. Starea calculatorului este definită de starea

procesorului (conţinutul registrelor) şi starea memoriei (conţinutul amplasamentelor). Această

stare este modificată de către procesor prin executarea instrucţiunilor programului. Fiecare

executare a unei instrucţiuni constituie o acţiune: o acţiune are ca efect trecerea în timp finit a

calculatorului dintr-o stare iniţială într-o stare finală. Acest efect este descris în specificaţiile

instrucţiunii.

Executarea unei instrucţiuni va fi considerată indivizibilă sau atomară, adică este interzisă

observarea sau definirea stării maşinii în timpul acestei execuţii. Timpul utilizat pentru

descrierea evoluţiei stării este un parametru t, care poate lua o serie de valori discrete

crescătoare, corespunzătoare începutului şi sfârşitului instrucţiunilor. Aceste instanţe sunt

numite puncte de observare, iar stările corespunzătoare ale maşinii sunt numite puncte

observabile. Prin abuz de limbaj, acest ultim termen desemnează în egală măsură şi punctele de

observare. Acestea permit să se asocieze o dată (valoarea curentă a lui t) unei stări a maşinii; o

atare stare datată defineşte un eveniment. Evenimentele permit reperarea modificărilor stării

maşinii. Începutul şi sfârşitul unei acţiuni a sunt evenimente datele cărora sunt notate început(a)

şi sfârşit(a); vom avea, evident, început(a)<sfârşit(a).

Executarea unui program se traduce, deci, într-o suită de acţiuni a1, a2,..., ai,..., cu

început(ai)<sfârşit(ai).

O astfel de suită este numită proces secvenţial (sau simplu proces).

Un proces poate, deci, fi descris cu ajutorul succesiunii evenimentelor început(a1),

sfârşit(a1), început(a2), sfârşit(a2),... Această suită de stări datate ale maşinii se numeşte

traiectorie temporală (sau istorie) a procesului. Putem de asemenea defini un proces ca o suită

de activităţi în sensul lui 2.1.

Mulţimea informaţiilor pe care acţiunile unui proces le pot consulta sau modifica se

numeşte contextul procesului. Reluând modelul de execuţie secvenţială introdus în 2.1,

contextul unui proces rezultant din executarea unui program conţine:

1) Contextul procesorului (cuvântul de stare şi registrele),

2) Un context în memorie, sau spaţiul de lucru (segmente procedură, date, stivă

de execuţie),

3) O mulţime de atribute ataşate procesului şi care specifică diferite proprietăţi:

Într-un mod mai riguros ar trebui să adăugăm aici “punctele întreruptible” care pot fi prezente în unele instrucţiuni de lungă durată; o executare a unei asemenea

instrucţiuni poate fi considerată o suită de mai multe acţiuni.

Pentru comoditatea expunerii considerăm, că sfârşitul unei acţiuni şi începutul acţiunii următoare sunt două evenimente distincte, datele cărora sunt diferite, deşi stările

corespunzătoare sunt identice.

Page 46: spora

46

a) Nume. Numele unui proces, care serveşte pentru identificarea lui, este de

regulă, un număr intern atribuit la crearea procesului şi care permite să se ajungă la

reprezentarea contextului său (v.4.2).

b) Prioritate. Prioritatea proceselor permite ordonarea lor pentru alocarea

procesorului (v.4.2, 4.3). Dacă toate procesele au aceeaşi prioritate, alocarea se face

conform ordinii “primul sosit, primul servit”.

c) Drepturi. Drepturile unui proces specifică operaţiile care îi sunt permise, în

scopul asigurării protecţiei informaţiei (v. 5.1.4).

Traiectoria temporală a unui proces este definită de şirul stărilor contextului său

(procesor şi memorie) preluate după execuţia fiecărei instrucţiuni. Prin definiţie, starea restului

maşinii nu este modificată de execuţia procesului.

48.Relaţii între procese

Vom cerceta în continuare execuţia unei mulţimi de procese şi interacţiunea

reciprocă a acestora. Noţiunile, introduse în 3.2.1 pot fi extinse pentru o mulţime de procese:

traiectoria temporală a unei mulţimi de procese este şirul evenimentelor formate de

începuturile şi sfârşiturile acţiunilor rezultante din executarea programelor acestor procese.

contextele unor procese diferite pot avea părţi comune. Două procese, contextele

cărora sunt disjuncte, se numesc independente; ele nu pot avea interacţiuni reciproce.

Partea contextului, care aparţine unui singur proces, se numeşte context privat al

procesului dat.

Exemplul 3.1. Fie două procese care partajează o procedură reentrantă.

Segmentul executabil, care conţine această procedură aparţine contextului comun.

Segmentul de date şi stiva fiecărui proces formează contextul lor privat. ◄

49.Mulţimi de procese. Paralelism

Să considerăm două programe distincte P şi Q, fiecare având î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 întâi tot procesul p, apoi procesul q la fel în întregime,

schema 2: sunt executate şiruri de instrucţiuni ale procesului p în mod alternativ cu

şiruri de instrucţiuni ale procesului q, şi tot aşa până 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 execuţie introducem noţiunea nivel de observare.

Putem considera o suită de acţiuni ale unui proces ca o acţiune unică, adică să observăm

derularea unui proces considerând o unitate de execuţie

Page 47: spora

47

mai puţin fină decât instrucţiunea. De exemplu, dacă vom redefini noţiunea de acţiune

elementară ca execuţie a unei proceduri, traiectoria procesului va conţine doar stările definite de

fiecare apel şi retur de procedură. Nivelul de observare cel mai fin (cel al instrucţiunilor) este

numit nivel de bază.

Să ne situăm mai întâi la nivelul de observare la care, prin convenţie, executarea completă a

fiecărei dintre programele P şi Q reprezintă o acţiune unică. Definiţiile care urmează sunt pentru

acest nivel.

a) schema de tip 1 este a unei execuţii secvenţiale a lui p şi q. Ea este caracterizată de

relaţiile:

sfârşit(q) < început(p) sau sfârşit(p) < început(q)

b) schemele de tip 2 sau 3 sunt scheme de execuţie paralelă. Ele sunt

caracterizate de

sfârşit(p) > început(q) sau sfârşit(q) > început(p).

Revenim la nivelul de bază. Putem face o distincţie între schemele 2 şi 3. Într-adevăr, în

schema 2, din considerente de existenţă a unui singur procesor, la un moment de timp dat doar o

singură acţiune 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ă observaţii importante sunt necesare:

1) Diferenţa acestor scheme de execuţie este legată de alegerea nivelului de

observare. Astfel, la nivelul de bază, diferenţa dintre schemele 1 şi 2 dispare: ambele sunt

secvenţiale.

Exemplu 3.2. Utilizatorii unui sistem de operare, care funcţionează în timp

partajat pe un singur procesor, au impresia că programele lor sunt executate în mod

paralel, deoarece nivelul lor de observare este cel al comenzilor limbajului de

comandă, compuse din multe instrucţiuni. La nivelul de bază, însă, aceste instrucţiuni

sunt atomare şi executate de procesor în mod secvenţial. Exemplul celor două

reactoare chimice, prezentate în 3.1.2, conduce la observaţii analogice. ◄

2) Alegerea nivelului de bază depinde de fineţea fenomenelor, care dorim să le

considerăm elementare. Dacă trebuie să studiem executarea instrucţiunilor în “pipe-line” pe

un procesor microprogramat, în calitate de nivel de bază va fi ales nivelul

(1)

(2)

(3)

p q

p q

p q p q p q

Fig. 3.2. Executarea unei mulţimi de

procese

Page 48: spora

48

microinstrucţiunilor, iar contextul va fi completat cu memoria microprogramelor şi

registrele interne.

Vom examina realizarea, la nivelul de bază, a unei scheme de execuţie de tipul 2. La fiecare

realocare a procesorului, contextul procesului curent trebuie salvat, pentru a permite reluarea

ulterioară a acestei execuţii. Dacă memoria are o capacitate suficientă pentru a păstra toate

segmentele, doar contextul procesorului trebuie salvat. Dacă memoria principală poate conţine,

la un moment de timp dat, doar segmentul procedură şi datele unui singur proces, aceste

segmente de asemenea trebuie salvate pe disc. Această remarcă justifică definiţia operaţională,

adesea întâlnită, a contextului unui proces ca mulţime a informaţiilor care trebuie salvată

pentru a permite reluarea ulterioară a procesului, dacă execuţia acestuia a fost întreruptă.

50.Concurenţa proceselor. Resurse virtual

Situaţia descrisă de schemele 1 şi 2 nu rezultă dintr-o legătură logică între p şi q, ci doar din

existenţa unui singur procesor. Ea poate fi caracterizată astfel: fie o mulţime de procese

contextele cărora 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 situaţia descrisă, procesorul este o resursă critică pentru procesele p şi

q.

Observăm că excluderea mutuală a unei resurse conduce la “serializarea” execuţiei

proceselor concurente, în cazul unor acţiuni, care cer această resursă (în exemplul dat, toate

acţiunile). Schemele 1 şi 2 diferă doar prin nivelul de fineţe la care este executată serializarea.

Funcţionarea corectă a unei mulţimi de procese, care participă la îndeplinirea unei lucrări

comune, implică relaţii logice de cooperare (v.3.1.1). Este comod să se separe această cooperare

de concurenţa pentru resursele fizice cu scopul de a simplifica înţelegerea şi aplicarea celor două

tipuri de relaţii. Pentru aceasta este folosită noţiunea de resurse virtuale: fiecărei resurse fizice

critice i se asociază tot atâtea copii imaginare (sau virtuale) ale acestei resurse câte procese

concurente solicită utilizarea ei. Suntem nevoiţi să tratăm două probleme distincte:

1) respectarea relaţiilor de cooperare între procesele, care, fiecare posedă

(conceptual) resursele fizice solicitate şi pentru care paralelismul în execuţie nu este

restricţionat de competiţia pentru resurse,

2) reglarea problemei de concurenţă pentru resursele fizice printr-o serializare

convenabilă a execuţiei proceselor în cauză. Se va spune în acest caz, că realizăm 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ă ataşăm fiecărui 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

menţionat, că această schemă logică reprezintă doar o notaţie compactă pentru mulţimea

schemelor reale posibile şi că ele sunt obligatoriu de forma 1 sau 2 din considerentele unicităţii

Page 49: spora

49

procesorului. Pentru o schemă reală şi una virtuală a unui proces dat este păstrată doar ordinea de

succesiune a evenimentelor (începutul şi sfârşitul acţiunii) şi nu sunt păstrate valorile absolute

ale intervalelor de timp, care le separă. În absenţa altor informaţii, nu putem spune nimic apriori

despre ordinea evenimentelor, asociate unor procese distincte. Timpul folosit la reperarea

evenimentelor în schema logică este numit timp logic; relaţiile sale cu timpul real sunt

prezentate în fig.3.3. a1 a2 +------+-----------------+------+ procesul p b1 b2 (timp logic) +--+-------+---------+ procesul q

a1 a2

+------+---+ +----------+ +----+------+ p (timp real, execuţia

1)

+--+--+ +-----+---------+ q

b1 b2

a1 a2

+---+ +---+-----------------+------+ p (timp real, execuţia

2)

+--+----+ +---+---------+ q

b1 b2

În toate cazurile a1 precede a2, b1 precede b2.

Fig.3.3. Timpul logic şi timpul real

Vom considera, că evoluţia proceselor are loc în timp logic, adică vor fi interzise orice

ipoteze despre viteza relativă a proceselor în cauză: aceasta este consecinţa simplificării

considerabile, introduse de noţiunea de resurse virtuale, care permite ignorarea mecanismelor de

alocare. O singură excepţie, totuşi va fi făcută pentru studierea sincronizării temporale, în care

timpul fizic intervine în mod precis ca măsură a duratei şi nu numai ca mod de reperare relativă.

Page 50: spora

50

51. Excludere mutual 51

52. Sincronizarea proceselor 51

53. Exprimarea şi implementarea restricţiilor de precedare 51-52

54. Probleme de realizare a sincronizării 52

55. Monitorul – mecanism de sincronizare. Definiţii. Ex. 53

56. Implementarea sincronizării. Probleme-tip 53

57. Administrarea unei resurse partajate 54

58. Alocarea resurselor banalizate 54

59. Modelul cititorului şi redactorului 55

60. Comunicarea între procese 55

61. Modelul producătorului şi consumatorului 56

62. Primitive de comunicare 57

63. Aplicaţii : relaţia client-server 58

64. Administrarea intrărilor-ieşirilor 59

65. Administrarea unui periferic 59

66. Buferizarea imprimării 60

67. Sincronizare temporală 61

68. Gestionarea dinamică a proceselor 63

69. Sincronizarea în Windows 65

70. Procese şi fire 65

71. Necesitatea sincronizării 66

72. Structura mecanismului de sincronizare în Windows 67

73. Administrarea obiectelor de sincronizare în Windows 67

74. Excluderea mutual 68

75.Evenimentele 68

Page 51: spora

51

51. Excludere mutual (3.2.2.1)

Fie o mulţime de procese contextele cărora 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 situaţia descrisă, procesorul este o resursă critică

pentru procesele p şi q.

52. Sincronizarea proceselor (cap. 3)

Sincronizarea reprezintă derularea concomitentă (se petrec în acelaş timp) a proceselor ce

folosesc resurse commune, de obicei un hardware device sau o mulțime de variabile. Sincronizarea

îşi propune 4 acţiuni cheie:

accesarea de către o mulţime de procese a unei resurse partajate

comune,

comunicarea între procese,

gestionarea perifericelor şi intrărilor-ieşirilor tamponate,

sincronizare temporală.

53. Exprimarea şi implementarea restricţiilor de precedare (3.3.1)

(1)

(2)

(3)

p q

p q

p q p q p q

Fig. 3.2. Executarea unei mulţimi de procese

Page 52: spora

52

Exemplul 3.4. Procesul p transmite informaţii 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 condiţia: sfârşit(scriere(a)) < început(citire(a))

Această relaţie exprimă restricţia, că citirea lui a de către q nu poate începe înainte de

terminarea scrierii lui a de către p.

Restricţiile de sincronizare pot fi exprimate prin următoarele două forme echivalente:

1. Se va impune o ordine de succesiune în timp logic pentru unele puncte ale

traiectoriei temporale ale procesului,

2. Se va impune unor procese o condiţie de autorizare a depăşirii acestor puncte

ale traiectoriei lor temporale.

Punctele privilegiate astfel se vor numi puncte de sincronizare. Expresia (2) arată, că

restricţiile de sincronizare pot fi satisfăcute impunând un proces “să aştepte” să execute o acţiune

până când o oarecare condiţie va fi satisfăcută. Această noţiune de aşteptare nu poate fi exprimată

cu ajutorul instrumentarului introdus până acum; pentru aceasta vom introduce o nouă stare pentru

un proces, stare în care procesul se zice în aşteptare sau blocat, prin opoziţie stării activ,

considerate până acum în mod implicit. Se numeşte blocare tranziţia activaşteptare şi

deblocare tranziţia inversă. Specificarea proceselor se va produce în două etape:

1) definirea punctelor de sincronizare pentru fiecare proces,

2) asocierea unei condiţii de depăşire fiecărui punct de sincronizare, condiţie

exprimată prin intermediul variabilelor de stare a sistemului.

54. Probleme de realizare a sincronizării

Exemplul 3.8 sincronizare a proceselor p si q. var e : eveniment memorizat;

procesul p procesul q

scriere(a); <debut_q>;

e:=sosit; aşteptare(e);

<continuare_p> citire(a)

Implementarea condiţiilor de sincronizare nu poate fi corect realizată numai cu ajutorul

operaţiilor de aşteptare. Consultarea şi modificarea variabilelor de stare, care intervin în aceste

condiţii, trebuie să fie executate în regim de excludere reciprocă. Observaţia dată ne impune să

introducem un mecanism de sincronizare, care în mod automat ar asigura acest regim de

funcţionare (e vorba de monitor).

Page 53: spora

53

procedura debut_citire;

if non fact then

term.aşteptare

endif

begin -- iniţializare

fact := false

end

end sinc

55. Monitorul – mecanism de sincronizare. Definiţii. Exemple de utilizare (3.3.3)

Un monitor este o metodă de sincronizare a două sau mai multe sarcini ce folosesc o resursă

comună, de obicei un hardware device sau o mulțime de variabile. În concurența bazată pe

monitor, compilatorul sau interpretorul introduce cod, în mod transparent, pentru blocarea sau

deblocarea unor proceduri specificate, fără a fi nevoie ca programatorul să acceseze explicit

primitive de sincronizare. Un monitor este constituit dintr-o mulţime de variabile de stare şi o

mulţime de proceduri. Monitorul poate fi utilizat doar prin apelarea procedurilor sale externe;

acestea permit blocarea sau deblocarea proceselor conform specificaţiilor problemei. Condiţiile de

blocare sau deblocare sunt exprimate ca funcţie ale variabilelor de stare, iar mecanismul de

execuţie a monitorului garantează manipularea acestor variabile în regim de excludere mutuală. În

fine, un monitor conţine un fragment de cod de iniţializare, executat o singură dată la crearea

monitorului.

Exemplul de utilizare 3.10. sinc: monitor;

var fact: boolean;

term: condiţie;

procedura terminare_scriere;

begin

fact:=true;

term.semnalizare

end

56. Implementarea sincronizării. Probleme-tip (3.4.1)

Experienţa demonstrează, că problemele de sincronizare logică întâlnite în practică pot fi

reduse, în marea lor majoritate, la combinaţia unui număr mic de situaţii elementare, schemele de

soluţionare ale cărora sunt cunoscute. Secţiunile 3.4.2 – 3.4.5 sunt consacrate studierii acestor

probleme-tip, utilizând instrumentarul de bază, pus la dispoziţie de monitoare. Problemele-tip sunt

următoarele:

Page 54: spora

54

accesarea de către o mulţime de procese a unei resurse partajate

comune,

comunicarea între procese,

gestionarea perifericelor şi intrărilor-ieşirilor tamponate,

sincronizare temporală.

57. Administrarea unei resurse partajate (3.4.2)

Considerăm o resursă (fizică sau logică) partajată de o mulţime de procese. Utilizarea acestei

resurse trebuie să respecte nişte reguli de utilizare sau restricţii de integritate, pentru fiecare

resursă. O modalitate de garantare a respectării regulilor de utilizare a unei resurse constă în

adoptarea următoarei 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 căruia impune respectarea restricţiilor de integritate.

Cel mai simplu caz este acela al unei resurse pentru care singura restricţie de integritate este

de a fi utilizată în excludere reciprocă. Simpla grupare a procedurilor sale de acces într-un monitor

unic garantează respectarea acestor restricţii.

58. Alocarea resurselor banalizate (3.4.2.1)

Considerăm o resursă pentru care există un număr fix de N exemplare. Un proces poate

accesa la cerere n unităţi din cele N, le poate utiliza şi apoi elibera. O unitate, folosită de un proces,

se numeşte alocată procesului, care o utilizează, pentru toată perioada de la accesare până la

eliberare. Toate unităţile sunt echivalente din punctul de vedere al proceselor utilizatoare, vom mai

zice că resursa este banalizată. Zonele-tampon din memoria principală sau pe disc, unităţile de

bandă magnetică, etc. sunt exemple de resurse banalizate.

Vom admite următoarele 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ă (ne alocată de alt proces),

operaţia de eliberare este aplicată mereu ultimelor resurse,

obţinute de procesul care execută eliberarea,

Page 55: spora

55

o cerere de alocare este blocantă în caz de eşec (număr

insuficient de unităţi libere).

59. Modelul cititorului şi redactorului (3.4.2.2)

Să considerăm un fişier manipulat de procese din două clase diferite: cititori (read-only) şi

scriitori (read-write). Fie pentru un moment arbitrar de timp ncit şi nscr numărul de cititori şi de

scriitori. Definim restricţiile:

(nscr=0) şi (ncit0) -- fişier în citire

sau (nscr =1) şi (ncit=0) -- fişier în scriere

Fie fich un monitor care asigură respectarea acestor restricţii. Impunem următoarea formă a

acceselor la fişier:

proces cititor proces scriitor

fich.debut_citire; fich.debut_scriere;

<acces citire> <acces scriere>

fich.terminare_citire; fich.terminare_scriere;

Procedurile debut_citire, terminare_citire, debut_scriere, terminare_scriere trebuie să

asigure respectarea restricţiilor de mai sus. Vom implementa aceste restricţii autorizând depăşirile;

pentru aceasta este necesar să fie precizate priorităţile între cititori şi scriitori.

Exemplu, presupunem că cititorii au prioritate în faţa

redactorilor (o scriere nu va fi autorizată, dacă există cititori în aşteptare). Definim

următoarele variabile de stare:

scr = o scriere este în curs (valoare booleană)

nc = numărul de cititori în aşteptare sau în curs de citire

În acest caz, condiţiile de depăşire se vor exprima după cum urmează:

aut(citire) : scr=false (nu există scrieri curente)

aut(scriere): scr=false şi nc=0 (nici scrieri nici citiri în curs, nici cititori

în aşteptarea)

60. Comunicarea între procese (3.4.3)

Page 56: spora

56

Procesele pot comunica prin accesarea unei mulţimi 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 secvenţe scurte şi bine protejate. Pentru cazuri generale

sunt utilizate alte moduri de comunicare.

Exemple: a) o schemă de bază pentru comunicarea prin mesaje - modelul producătorului şi

consumatorului, realizat cu ajutorul monitoarelor. b) O altă posibilitate, constă în a considera

operaţiile de comunicare ca un fel de mecanisme primitive de sincronizare. c) o aplicaţie frecventă

de comunicare – modelul client-server.

61. Modelul producătorului şi consumatorului (3.4.3.1)

O schemă uzuală de comunicare este cea în care un proces (producătorul) trimite mesaje

unui alt proces (consumatorul), utilizând un tampon (monitorul) în memoria comună. Mesajele

sunt de lungime fixă şi capacitatea tamponului este de N mesaje. Specificaţiile comunicaţiei sunt

următoarele:

un mesaj dat poate fi preluat doar o singură dată după ce a fost

depozitat în tampon,

un mesaj nu poate fi pierdut; dacă tamponul conţine N mesaje

nepreluate, nu pot fi depozitate aici altele

o operaţie “imposibilă” (depozitare într-un tampon plin /

preluare dintr-un tampon vid) blochează procesul, care încearcă să o execute.

Condiţiile de depăşire pot fi exprimate după cum urmează, notând prin n numărul de mesaje

din tampon, care nu au fost încă preluate:

aut(depozitare) : n < N -- tamponul nu este plin

aut(preluare) : n > 0 -- tamponul nu este vid

Respectarea acestor restricţii este asigurată de un monitor tampon, utilizat după cum urmează:

proces producător proces consumator

... ...

produce(mesaj_emis); tampon.preluare(mesaj_recepţionat);

tampon.depozitare(mesaj_emis); consumator(mesaj_recepţionat);

Page 57: spora

57

62. Primitive de comunicare (3.4.3.2)

Schimbul de mesaje între procese, în afară de funcţia de transmitere a informaţiei, poate fi

utilizat şi pentru ordonarea evenimentelor în cadrul unor procese distincte, deoarece emiterea unui

mesaj precede întotdeauna recepţia sa. Operaţiile de schimb de mesaje pot fi definite ca nişte

mecanisme primitive şi să le utilizăm pentru sincronizarea proceselor. Primitivele de bază în

comunicarea prin mesaje sunt: emitere(mesaj,destinaţie) şi recepţie(mesaj,origine). Specificările

acestor primitive trebuie să precizeze:

natura şi forma mesajelor,

modul de adresare a proceselor emiţătoare şi destinatare,

modul de sincronizare a acestor procese,

tratarea erorilor.

1) Natura mesajelor

Lungimea poate fi constantă sau variabilă. Mai frecvent sunt utilizate mesajele de lungime

constantă, care pot fi create mai simplu, mesajele de lungime variabilă vor fi transmise prin

referinţă, pasând adresa fizică sau identificatorul informaţiei transmise.

2) Modul de adresare

Procesele, care fac schimb de mesaje, se pot desemna reciproc prin numele lor (desemnare

directă) sau pot utiliza numele unui obiect intermediar ori cutie poştală (desemnare indirectă).

Aceste nume sunt folosite ca parametri origine şi destinaţie.

În cazul desemnării directe parametrul origine a primitivei recepţie poate fi interpretat în

două moduri:

fie ca dată: receptorul specifică explicit că aşteaptă un mesaj de

la un destinatar special (recepţie selectivă),

fie ca rezultat: receptorul primeşte un mesaj care i-a fost

adresat împreună cu identitatea emiţătorului.

În cazul desemnării indirecte asocierea proceselor cutiilor poştale poate fi statică sau

dinamică. În ultimul caz, sunt utilizate două primitive conectare şi deconectare pentru ataşarea

procesului la o cutie poştală (în calitate de receptor) şi de abrogare a acestei ataşări, respectiv. În

unele sisteme un receptor sau mai multe pot fi ataşate unei cutii poştale date; cutiile poştale supuse

unor asemenea restricţii sunt adesea numite porţi.

3) Moduri de sincronizare

În caz general, avem două moduri de sincronizare:

Page 58: spora

58

Schema producător-consumator, în care cutia poştală este

realizată printr-o zonă tampon. Emiterea nu este blocantă, cu excepţia cazului în care

tamponul este plin.

Schema rendez-vous, în care emiţătorul este blocat până la

preluarea mesajului de către receptor. Această schemă poate fi considerată caz limită a

precedentei cu lungimea nulă a tamponului.

În fine, atunci când un proces este asociat în recepţie la mai multe porţi, poate fi definit un

mod de sincronizare, zis aşteptare multiplă, în care sosirea unui mesaj la o oarecare din aceste

porţi deblochează receptorul.

4) Tratarea erorilor

Scopul tratării erorilor este de a evita blocările infinite ale proceselor, care se pot produce în

diverse circumstanţe:

Emiterea unui mesaj cu o destinaţie (proces sau poartă)

inexistentă. În acest caz primitiva nu este blocantă; eroarea este tratată prin emiterea unui

cod de eroare sau printr-o deviere.

Distrugerea unui proces de la care alte procese aşteaptă un

mesaj sau un răspuns: procesele în aşteptare sunt blocate şi recepţionează un cod de eroare.

63. Aplicaţii: relaţia client-server (3.4.3.3)

O aplicaţie curentă a comunicărilor între procese este relaţia client-server. Un proces server

are în şarjă îndeplinirea unor servicii (executarea unui program predefinit) proceselor client.

Pentru aceasta poate fi utilizată următoarea schemă:

procesul server procesul client

ciclu poartă_serviciu.emitere(cerere)

poartă_serviciu.recepţionare(cerere)

<executare serviciu> ...

[poartă_client.emitere(rezultat)] ...

endciclu [poartă_client.recepţionarere(rezultat)]

Procesul server este asociat unei porţi, unde clienţii îşi depun cererile, trimiţând cereri; el este

blocat atâta timp cât nu există cereri de servicii în aşteptare.

Page 59: spora

59

Serviciul cerut poate conţine trimiterea la client a rezultatului. În acest caz clientul trebuie să

trimită serverului în cererea sa numărul unei porţi la care el se va bloca în aşteptarea rezultatului.

64. Administrarea intrărilor-ieşirilor (3.4.4)

Vezi întrebările nr. 44, 65 şi 66.

65. Administrarea unui periferic (3.4.4.1)

Fiecărui periferic îi este asociat un monitor procedurile externe ale căruia permit executarea

intrărilor-ieşirilor la acest periferic. Acest monitor are următoarea formă generală (pentru un

sistem mono-utilizator):

perif: monitor; var ..., sfr_schimb_i,...: condiţie;

<declaraţiile variabilelor de stare ale perifericului>

...

procedura schimb_i(<parametri>);

begin

<mascarea întreruperilor>;

if starea ≠ preg then

<tratare eroare(perifericul nu este gata)>

endif;

lansare_transfer_i(parametri);

sfr_schimb_i.aşteptare; -- întrerupere demascată

if starea ≠ ok then -- în timpul aşteptării

<tratare eroare(incident de transfer)>

endif;

<demascare întreruperi>

end;

...

Page 60: spora

60

begin

<iniţializare>

end

end perif

Procedura lansare_transfer_i pregăteşte programul pentru schimbul cerut şi lansează execuţia

sa. Procesele apelante aşteaptă sfârşitul transferului datorită condiţiei sfr_schimb_i. Sosirea unei

întreruperi, care marchează sfârşitul schimbului de tip i provoacă în mod automat executarea

următoarei secvenţe:

if sfr_schimb_i.vid then <tratarea eroare întrerupere care nu este aşteptată>

else sfr_schimb_i.semnalizare

endif

Pentru un proces care execută o intrare-ieşire apelând o procedură de schimb a acestui

monitor, totul se petrece ca şi cum schimbul este sincron: la returul din procedură, informaţia a

fost efectiv transferată (sau o eroare a fost detectată şi semnalizată). Mecanismul de blocare evită

aşteptarea activă şi procesorul poate fi utilizat în timpul transferului de un alt proces.

66. Buferizarea imprimării

Avem nevoie de trei tampoane tm1 şi tm2 de capacitate N1 şi N2 în memoria centrală şi unul

pe disc, td, de lungime Ndisc. Pentru simplitate presupunem că transferurile se fac cu blocuri

constante egale cu o linie. Fiecare tampon este comandat de un monitor cu aceeaşi structură care

are rolul de a asigura excluderea mutuală şi sincronizarea condiţiilor tampon plin şi tampon vid.

Definind pointerii top şi coadă locali fiecărui monitor, procedurile de depozitare şi preluare pot fi:

<pentru tamponul 1> <pentru tamponul 2>

procedura intrare(l:linie); procedura intrare(l:linie);

tm1[coadă] := l; tm2[coadă] := l;

coadă := coadă+1 mod N1 coadă := coadă+1 mod N2

procedura ieşire(var l:linie); procedura ieşire(var l:linie);

l := tm1[top]; l := tm2[top];

Page 61: spora

61

top := top+1 mod N1 top := top+1 mod N2

În monitorul tampon_disc operaţiile de depozitare şi preluare sunt intrări-ieşiri ce utilizează

mon. de gestionare a discului:

procedura intrare(l:linie); procedura ieşire(var l:linie);

disc.scriere(l,td[coadă]); disc.scriere(l,td[top]);

coadă := coadă+1 mod Ndisc top := top+1 mod Ndisc

Programul de intrare-ieşire este realizat prin cooperarea a patru procese programul cărora este

prezentat schematic mai jos (trei procese ale sistemului de operare şi procesul utilizator). Pentru a

simplifica expunerea au fost omise secvenţele de tratare a erorilor şi am admis, că sistemul

funcţionează în regim permanent fără limitarea numărului 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.

proces imprimare linie proces scriere_disc proces citire_disc

ciclu ciclu ciclu

tampon2.preluare(l); tampon1.preluare(l);

tampon_disc.citire(l);

impr.scriere(l); tampon_disc.scriere(l);

tampon2.depozitare(l);

endciclu endciclu endciclu

Imprimarea unei linii este cerută de procedura:

procedura scriere_linie(l:linie);

tampon1.depozitare(l)

Programele de mai sus sunt mult mai simple decât cele care folosesc direct întreruperile.

Structura modulară, introdusă de monitoare permite separarea totală a gestionării tampoanelor de

cea a perifericelor. Schimbarea capacităţii unui tampon modifică doar monitorul care comandă

acest tampon; înlocuirea unui periferic cu un altul implică rescrierea doar a monitorului, care

comandă acest periferic.

67. Sincronizare temporal (3.4.5)

Page 62: spora

62

Sincronizarea temporală face ca timpul să intervină nu numai ca mijloc de ordonare a

evenimentelor, dar şi ca măsură de durată absolută. Acest mod de sincronizare este utilizat în

aplicaţiile de timp real, care conţin interacţiuni cu organe externe (comanda proceselor industriale,

de exemplu). Sincronizarea temporală solicită folosirea unui ceas, realizat prin intermediul unui

oscilator cu quartz, care emite impulsuri la intervale regulate. Aceste impulsuri pot fi utilizate

pentru a declanşa o întrerupere la fiecare impuls sau pentru a decrementa în mod automat

conţinutul unui registru contor, o întrerupere este declanşată atunci când conţinutul acestui registru

atinge valoare 0.

valoarea absolută a timpului (ora absolută),

măsoară la orice moment timpul trecut de la o instanţă iniţială,

un registru, adică o listă a proceselor care

aşteaptă deblocarea, ordonat conform timpului absolut de deblocare.

Toate procesele, care apelează primitiva suspendare(t) (folosită pentru blocarea ceasul pe

durată t) sunt inserate în registru în poziţia, care corespunde orei sale absolute de deblocare.

Numim ora_de_bază ora absolută a ultimei înnoiri a ceasului, adică a ultimei iniţializări a

contorului; fie t_aşt ultima valoare încărcată. Ora absolută exactă este dată la fiecare moment de

timp de relaţia

ora_exactă = ora_de_bază + t_aşt - contor

(t_aşt - 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_aşt;

ora_de_bază poate, deci, fi iniţializată conform relaţiei

ora_de_bază := ora_de_bază + t_aşt

Variabila ora_de_bază, odată iniţializată, va fi corect întreţinută cu condiţia ca registrul să nu

fie nicicând vid; în caz general această condiţie va fi asigurată introducând un proces, numit

paznic:

procesul paznic

ciclu

suspendare(tmax)

endciclu

în care tmax este un interval foarte mare de timp, paznicul rămânând pentru toată perioada de

lucru în coada registrului.

Page 63: spora

63

Mecanismele descrise sunt realizate într-un monitor numit ceas, care are două intrări:

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 aşteptare, care conţine descriptorii proceselor. Un descriptor este format din numele

procesului şi timpul absolut de deblocare; firul de aşteptare este ordonat în ordinea creşterii

timpului deblocării.

68. Gestionarea dinamică a proceselor (3.5)

În sistemele concurente, mai ales în cele interactive, procesele sunt comandate dinamic.

Exemple: în Multics, un proces nou este creat odată cu admiterea unui nou utilizator; în Unix, la

executarea fiecărei comenzi. Crearea unui proces presupune alocarea resurselor şi iniţializarea

contextului. Distrugerea unui proces eliberează toate resursele care i-au fost alocate.

Primele primitive, propuse pentru gestionarea dinamică a proceselor, au fost fork şi join.

Aceste operaţii au fost introduse pentru organizarea executării paralele a programelor pe un sistem

multiprocesoral, noţiunea de proces nefiind încă clară. Vom descrie câteva variante ale acestor

primitive. Fie P o procedură. Instrucţiunea

id := fork(p),

executată de un proces p (părinte), 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 iniţial al lui q este o copie a lui p, mai puţin contorul ordinal, care este fixat la prima

instrucţiune a lui p. Procesul fiu se termină cu o primitivă, numită exit sau quit, care provoacă

dispariţia sa. După ce fork crează un proces fiu q, primitiva join q permite procesului părinte să

fixeze un punct de rendez-vous cu acest fiu. Executarea lui join q blochează procesul părinte până

când q nu va executa exit. Primitivele fork şi join au avantajele şi dezavantajele instrucţiunii go to

din programarea secvenţială.

Exemplul 3.15. În sistemul de operare Unix crearea unui proces poate fi realizată

de către interpretorul limbajului de comandă (shell) sau cu ajutorul instrucţiunii fork() de

un program. Ultima situaţie este prezentată schematic în fig.3.4.

Page 64: spora

64

Efectul instrucţiunii fork():

duplicarea procesului părinte;

returnarea valorii pid (numărului procesului fiu) în procesul părinte;

returnarea valorii 0 în procesul fiu:

procesul părinte procesul fiu

if (fork() == 0) if (fork() == 0)

codul procesului fiu codul procesului fiu

else else

codul procesului părinte codul procesului părinte

returnarea pid al procesului fiu ( 0) returnare 0

Altfel spus, în Unix primitiva fork (fără parametri) creează un proces al cărui spaţiu

de lucru este o copie a spaţiului de lucru a creatorului, inclusiv şi contorul ordinal.

Diferenţa poate fi determinată consultând valoarea returnată de primitivă (0 pentru fiu;

identificatorul fiului sau nil pentru părinte). O primitivă wait permite părintelui să

aştepte terminarea execuţiei unuia dintre programele fiu (fără a putea alege care anume,

dacă există mai multe). Un proces termină execuţia sa cu primitiva exit. Primitiva

exec(p) permite unui proces să schimbe contextul, apelând 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.

Ilustrăm folosirea primitivelor fork şi exec:

...

id := fork();

procesul 1

copie

date date

stivă

procesul părinte procesul fiu

procesul 2

stivă

Fig.4.4. Crearea proceselor cu ajutorul instrucţiunii fork

Page 65: spora

65

if id = 0 then -- eu sunt fiul

exec(p) -- programul fiului

else -- eu sunt părintele

if id = -1 then -- nil : creare imposibilă

<tratare eroare>

else

<programul părintelui>

endif

endif

Primitiva wait este utilizată după cum urmează:

id := wait(cod) -- blocare până la terminarea programului unuia dintre fii

... -- id = numărul programului fiu terminat, cod = cauza

terminării

69. Sincronizarea în Windows (3.6)

Platforma pe 32 de biţi pune la dispoziţia programatorului instrumente evoluate pentru

multiprogramare, atât la nivelul unei mulţimi de lucrări, cât şi a unei lucrări singulare. Poate să

apară întrebarea CÂND să fie utilizată multiprogramarea în cadrul unei singure aplicaţii.

Răspunsul este foarte simplu: atunci când dorim ca mai multe fragmente de cod să fie executate

simultan (pseudosimultan, dacă există mai multe fragmente decât procesoare). De exemplu,

dacă dorim ca unele activităţi să fie îndeplinite în regim de fond sau programul să continue să

reacţioneze la unele evenimente exterioare în timpul îndeplinirii unor calcule foarte

„costisitoare”. Pot fi aduse şi alte exemple.

70. Procese şi fire (3.6.1)

Numim proces în Windows o instanţă (un exemplar, o stare) a programului, încărcat în

memoria operativă. Această instanţă poate crea fire (thread) - secvenţe de instrucţiuni, care

urmează a fi executate. Este important să se înţeleagă că în Windows anume firele sunt

Page 66: spora

66

executate (nu procesele!), fiecărui proces fiindu-i asociat minimum un fir, numit firul principal al

aplicaţiei.

Deoarece în realitate există mult mai multe fire decât procesoare fizice, firele vor fi executate

secvenţial, timpul de procesor repartizându-se între fire. Dar viteza mare de execuţie şi frecvenţa

mare de comutare a firelor lasă impresia unei execuţii paralele a acestora.

Stările elementare ale unui fir sunt aceleaşi ca şi în cazul proceselor: ales (exe), eligibil

(ready) şi blocat (wait). Starea blocat este asociată aşteptării unui anume eveniment. Când

evenimentul se produce firul este trecut în mod automat în starea eligibil.

În cadrul sistemului de operare Windows există două tipuri de fire – fire interactive, care

execută un ciclu propriu de prelucrare a mesajelor (de exemplu, firul principal al unei aplicaţii) şi

fire de lucru, care sunt funcţii simple. În ultimul caz execuţia firului se încheie atunci când

calculele, generate de funcţia respectivă, iau sfârşit.

Merită atenţie şi modalitatea organizării ordinii de execuţie a firelor. Algoritmul FIFO este

departe de a fi cel mai optimal. În Windows toate firele sunt ordonate conform priorităţilor.

Prioritatea unui fir este un număr întreg de la 0 la 31 şi este determinată de prioritatea

procesului, care a generat firul şi prioritatea relativă a firului. În acest mod se ajunge la o

flexibilitate maximă, fiecărui fir punându-i-se la dispoziţie – în caz ideal – exact atâta timp de

procesor, cât are nevoie.

Prioritatea firului poate fi modificată dinamic. Firele interactive, care au prioritatea Normal,

sunt executate în mod deosebit de către sistem, prioritatea acestor fire fiind majorată, atunci când

procesul, care le-a generat, se află în planul central (foreground). În rezultat, aplicaţia curentă

reacţionează mai repede la cererile utilizatorului.

71. Necesitatea sincronizării (3.6.2)

Când un proces este creat în mod automat este creat firul principal al acestuia. Acest fir poate

crea în timpul execuţiei alte fire, care la fel pot crea fire noi şi aşa mai departe. Timpul de procesor

fiind repartizat între fire, fiecare fir „lucrează” în mod independent.

Toate firele unui proces împart resursele comune, de exemplu, spaţiul de adrese al memoriei

operative sau fişierele deschise. Aceste resurse aparţin întregului proces, deci şi fiecărui fir.

Fiecare fir poate să utilizeze aceste resurse fără nici un fel de restricţii. În realitate, din cauza

multitaskingului controlat (preemptive multitasking - la orice moment de timp sistemul poate

întrerupe execuţia unui fir şi transmite controlul unui alt fir), se poate întâmpla ca un fir să nu fi

terminat încă lucrul cu o resursă comună oarecare, iar sistemul să treacă la un alt fir, care

Page 67: spora

67

utilizează aceeaşi resursă. Rezultatele pot fi imprevizibile. Asemenea conflicte se pot produce şi în

cazul unor fire, care aparţin chiar unor procese diferite. Problema poate să apară întotdeauna când

două sau mai multe fire folosesc o resursă comună. De aceeea este necesar un mecanism de

coordonare a lucrului firelor cu resurse comune. În Windows acest mecanism se numeşte

sincronizarea firelor (thread synchronization).

72. Structura mecanismului de sincronizare în Windows (3.6.3)

Mecanismul de sincronizare este un set de obiecte ale sistemului de operare Windows, create

şi gestionate program, comune pentru toate firele sistemului ş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 fişier 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 interfeţei grafice

(Graphic Device Interface), etc.

De obicei, sunt utilizate mecanismele (obiectele) de sincronizare, introduse mai sus:

excluderea mutuală (mutex), secţia critică (critical section), eveniment memorizat (event) şi

semaforul (semaphore), fiecare realizând metoda proprie de sincronizare. În calitate de obiecte

sincronizate pot fi chiar procesele sau firele (când un fir aşteaptă terminarea execuţiei unui proces

sau a unui alt fir), fişierele, dispozitivele de comunicaţie, etc.

Sensul mecanismelor de sincronizare constă în faptul, că fiecare poate să fie în starea set.

Atunci când un fir lucrează cu mecanismele de sincronizare (le creează, le modifică starea)

sistemul nu întrerupe execuţia firului, până nu va fi terminată această acţiune, adică toate operaţiile

finite din mecanismele de sincronizare sunt atomare (nu pot fi întrerupte).

Menţionăm de asemenea, că nu există nici o legătură reală între mecanismele de sincronizare

şi resurse. Mecanismele de sincronizare nu pot interzice accesul nedorit la o resursă, ele doar

indică firului momentul când acesta poate accesa resursa, sau când acesta trebuie să aştepte.

73. Administrarea obiectelor de sincronizare în Windows (3.6.4)

Crearea unui obiect de sincronizare se produce prin apelarea unei funcţii speciale din WinAPI

de tipul Create (ex.,CreateMutex). Acest apel returnează descriptorul obiectului (handle), care

poate fi folosit de toate firele procesului dat. Un obiect de sincronizare poate fi accesat şi dintr-un

alt proces, dacă acest proces a moştenit descriptorul obiectului dat, sau folosind funcţia de

deschidere a unui obiect (Open). Obiectului, dacă el nu este destinat doar pentru uz intern (în

Page 68: spora

68

interiorul unui singur proces), în mod obligator i se acordă un nume unic. Nu poate fi creat un

eveniment memorizat şi un semafor cu acelaşi nume.

Folosind descriptorul poate fi determinată starea curentă a obiectului cu ajutorul funcţiilor de

aşteptare. De exemplu, funcţia WaitForSingleObject(x, y) cu doi parametri (primul este

descriptorul obiectului, iar al doilea – timpul de aşteptare în ms) returnează WAIT_OBJECT_0,

dacă obiectul se află în starea set (adică nu aparţine nici unui fir şi poate fi utilizat pentru

sincronizare), WAIT_TIMEOUT – dacă a expirat timpul de aşteptare şi WAIT_ABANDONED,

dacă obiectul de sincronizare nu a fost eliberat înainte ca firul, care-l comanda, să se fi terminat.

Dacă timpul de aşteptare este egal cu 0, atunci funcţia returnează rezultatul imediat, în caz contrar,

aşteaptă intervalul de timp indicat. În cazul în care starea obiectului de sincronizare va deveni set

până la expirarea acestui timp, funcţia returnează WAIT_OBJECT_0, altfel - WAIT_TIMEOUT.

Dacă în parametrul timp este indicată constanta simbolică INFINITE, funcţia va aştepta până

când starea obiectului va deveni set, fără vre-o restricţie.

Starea mai multor obiecte poate fi aflată cu ajutorul funcţiei WaitForMultipleObjects. Pentru

încheierea lucrului cu un obiect de sincronizare şi eliberarea descriptorului se apelează funcţia

CloseHandle. Este important de ştiut, că apelarea unei funcţii de aşteptarea blochează firul curent,

adică atâta timp cât un fir se află în starea de aşteptare el nu are acces la procesor.

74. Excluderea mutual (3.6.4.1)

Cum a fost menţionat deja, mecanismele de excludere mutuală (mutex-ele, de la MUTual

EXclusion) permit coordonarea accesului la o resursă partajată (processor de ex.). Starea set a

obiectului corespunde momentului de timp în care obiectul nu aparţine nici unui fir şi poate fi

„utilizat”, iar starea reset – momentului când un fir oarecare controlează deja mutex-ul. Accesarea

va fi permisă doar după eliberare.

Pentru a lega mutex-ul de firul curent trebuie apelată una din funcţiile de aşteptare. Firul,

căruia îi aparţine mutex-ul, îl poate „ocupa” de mai multe ori, fără autoblocare, însă mai apoi

acesta va trebui eliberat tot de atâtea ori cu ajutorul funcţiei ReleaseMutex.

75. Evenimentele (3.6.4.2)

Obiectele-evenimente sunt utilizate pentru a informa firele, care sunt în aşteptare, despre

producerea unui eveniment. În Windows există două tipuri de evenimente – cu resetare manuală şi

automată. Resetarea manuală se execută cu funcţia ResetEvent. Aceste evenimente sunt folosite

Page 69: spora

69

pentru informarea mai multor fire, iar evenimentele cu resetare automată sunt utilizate pentru

informarea unui anumit fir, celelalte rămânând în aşteptare.

Funcţia CreateEvent crează un obiect-eveniment, funcţia SetEvent setează evenimentul în

starea set, iar funcţia ResetEvent resetează evenimentul. Funcţia PulseEvent setează evenimentul,

iar după semnalizarea firelor, care erau în aşteptare (toate în cazul resetării manuale şi doar unul la

resetarea automată), resetează obiectul. Dacă nu există fire în aşteptare, PulseEvent doar resetează

obiectul, fără semnalizare.

Page 70: spora

70

76. Semafoarele 71

77. Secţiunile critice 71

78 .Protejarea accesării variabilelor 71

79. Sincronizarea în MFC 71

80. Exemplu de sincronizare în Windows 72

81. Utilizarea secţiunilor critice în Windows 73

82. Structura RTL_CRITICAL_SECTION 75

83. Funcţii API pentru secţiunile critice 76

84. Clase de secţiuni critice 76

85. Depanarea secţiunilor critice 78

86. Administrarea proceselor. Realizarea excluderii mutuale. Specificarea problemei 78

87. Excluderea mutuală prin aşteptare activă 79

88. Algoritmul lui Dekker 79

89. Aşteptarea activă în sisteme multiprocesorale: Test & Set 80

90. Semaforul – instrument elementar pentru excluderea mutuală. Definiţii 81

91. Semaforul – Proprietăţi 82

92. Realizarea excluderii mutuale cu ajutorul semafoarelor 82

93. Funcţionarea şi structura unui nucleu de sincronizare. Stările unui proces. Fire de

aşteptare 84

94. Administrarea contextelor şi schemele primitivelor 86

95. Realizarea unui nucleu de sincronizare. Organizarea generală 88

96. Realizarea unui nucleu de sincronizare. Interfeţele 88

97. Realizarea unui nucleu de sincronizare. Structuri şi algoritmi 88

98. Realizarea unui nucleu de sincronizare. Realizarea monitoarelor. 90

99. Realizarea unui nucleu de sincronizare. Algoritmi de bază 90

100. Realizarea unui nucleu de sincronizare. Tratarea întreruperilor 92

Page 71: spora

71

76. Semafoarele

Un obiect-semafor este în ultimă instanţă un mutex cu contor. Acest obiect permite să

fie „ocupat” de un număr anume de fire, după care „ocuparea” va fi posibilă numai dacă unul

din fire va „elibera” semaforul. Semafoarele sunt utilizate pentru a limita numărul de fire,

care lucrează simultan cu resursa. La iniţializare se specifică numărul maxim de fire, la

fiecare „ocupare” valoarea contorului semaforului scade.

77. Secţiunile critice

Obiectul-secţiune critică permite programatorului să evidenţieze un fragment de cod în

care firul obţine acces la o resursă partajată, preîntâmpinând utilizarea resursei de mai mulţi

utilizatori. Pentru a utiliza resursa firul va intra mai întâi în secţiunea critică (apelarea

funcţiei EnterCriticalSection). Dacă intrarea a avut loc, nici un alt fir nu va avea acces la

aceeaşi secţiune critică, execuţia acestuia fiind suspendată. Reluarea se va produce în

momentul în care primul fir părăseşte secţiunea critică (funcţia LeaveCriticalSection).

Diferenţa de mutex constă în faptul că secţiunea critică este utilizată numai pentru firele unui

singur proces.

Cu ajutorul funcţiei TryEnterCriticalSection se poate stabili, dacă secţiunea critică este

liberă. Utilizând această funcţie, un proces, fiind în aşteptarea resursei, poate să nu se

blocheze, îndeplinind operaţii utile.

78. Protejarea accesării variabilelor

Există o serie de funcţii, care permit lucrul cu variabilele globale ale tuturor firelor, fără a

ne preocupa de sincronizare, deoarece aceste funcţii singure rezolvă problema sincronizării.

Aceste funcţii sunt InterlockedIncrement, InterlockedDecrement, InterlockedExchange,

InterlockedExchangeAdd şi InterlockedCompareExchange. De exemplu, funcţia

InterlockedIncrement incrementează valoarea unei variabile pe 32 biţi cu o unitate.

79. Sincronizarea în MFC(Microsoft Fundation Classes)

Biblioteca MFC conţine clase speciale pentru sincronizarea firelor (CMutex, CEvent,

CCriticalSection şi CSemaphore). Pentru utilizarea acestor clase trebuie consultaţi

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 aşa 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 conţine toate metodele

Page 72: spora

72

necesare. Clasa este proiectată în aşa mod, ca metodele ei să rezolve problema sincronizării,

adică în cadrul aplicaţiei să apară ca o simplă clasă. Obiectul de sincronizare MFC este inclus

în această clasă în calitate de membru privat şi toate funcţiile clasei, care realizează accesarea

resursei, îşi coordonează lucrul cu acest membru.

80. Exemplu de sincronizare în Windows

Prezentăm un exemplu simplu de lucru cu obiectul de sincronizare mutex [22].

#include <windows.h>

#include <iostream.h>

void main()

{

DWORD res;

// creăm 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 încercăm să ocupăm 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

{

// aşteptăm 10 s

cout<<"L-am prins! Aşteptare 10 secunde...\n"; cout.flush();

Sleep(10000);

// eliberăm obiectul

cout<<"Acum eliberăm obiectul\n"; cout.flush();

Page 73: spora

73

ReleaseMutex(mutex);

}

// închidem descriptorul

CloseHandle(mutex);

}

Pentru a controla modul de funcţionare a mecanismului de excludere mutuală se vor lansa

două instanţe ale acestei aplicaţii. Prima instanţă va ocupa obiectul imediat şi-l va elibera doar

peste 10 secunde. Numai după aceasta instanţa a doua va reuşi să ocupe obiectul. În acest

exemplu obiectul de sincronizare este folosit pentru sincronizarea proceselor, din care cauză în

mod obligatoriu trebuie să aibă nume.

81. Utilizarea secţiunilor critice în Windows

Exemplu: fie variabila m_pObject şi câteva 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 următorul 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;

Page 74: spora

74

}

În acest exemplu există pericolul potenţial de apelare m_pObject->SomeMethod() după ce

obiectul a fost distrus cu ajutorul delete m_pObject, deoarece în sistemele de operare cu

multitasking controlat execuţia oricărui fir poate fi întreruptă în cel mai neconvenabil moment

şi să înceapă execuţia unui alt fir. Pentru exemplul nostru momentul nedorit este atunci când

firul #1 a testat deja m_pObject, dar nu a reuşit să apeleze SomeMethod(). Execuţia firului #1 a

fost întreruptă şi a început execuţia firului #2. Iar firul #2 reuşise deja să apeleze destructorul

obiectului. Ce se va întâmpla atunci când firului #1 i se va acorda din nou timp de procesor şi

va fi apelat SomeMethod() al unui obiect deja inexistent? Greu de presupus.

Aici ne vin în ajutor secţiunile critice. Să modificăm exemplul de mai sus.

// Firul #1

void Proc1()

{

::EnterCriticalSection(&m_lockObject);

if (m_pObject)

m_pObject->SomeMethod();

::LeaveCriticalSection(&m_lockObject);

}

// Firul #2

void Proc2(IObject *pNewObject)

{

::EnterCriticalSection(&m_lockObject);

if (m_pObject)

delete m_pObject;

m_pObject = pNewObject;

::LeaveCriticalSection(&m_lockObject);

}

Page 75: spora

75

Fragmentul de cod inclus între ::EnterCriticalSection() şi ::LeaveCriticalSection() cu una

şi aceeaşi secţiune critică în calitate de parametru nu va fi executat nici o dată în mod paralel.

Aceasta înseamnă, că dacă firul #1 a reuşit să „acapareze” secţiunea critică m_lockObject,

încercarea firului #2 să intre în aceeaşi secţiune critică va conduce la blocarea acestuia până în

momentul când firul #1 va elibera m_lockObject prin apelul ::LeaveCriticalSection(). Invers,

dacă firul #2 a accesat secţiunea critică înaintea firului #1, acesta din urmă va fi nevoit “să

aştepte”, înainte de a începe lucrul cu m_pObject.

Menţionăm, că secţiunile critice nu sunt obiecte ale nucleului sistemului de operare.

Practic, tot lucrul cu secţiunile critice are loc in procesul care le-a creat. Din aceasta rezultă, că

secţiunile critice pot fi utilizate numai pentru sincronizare în cadrul unui proces.

82. Structura RTL_CRITICAL_SECTION

Este definită după cum urmează:

typedef struct _RTL_CRITICAL_SECTION

{

PRTL_CRITICAL_SECTION_DEBUG DebugInfo; // Folosit de sistemul de operare

LONG LockCount; // Contorul de utilizări

LONG RecursionCount; // Contorul accesării repetate din firul utilizatorului

HANDLE OwningThread; // ID firului utilizatorului (unic)

HANDLE LockSemaphore; // Obiectul nucleului folosit pentru aşteptare

ULONG_PTR SpinCount; // Numărul de cicluri goale înaintea apelării nucleului

}

RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;

Câmpul LockCount este incrementat cu o unitate la fiecare apelare ::EnterCriticalSection()

şi decrementat cu unu la fiecare apel ::LeaveCriticalSection().

În câmpul RecursionCount este păstrat numărul de apeluri repetate ::EnterCriticalSection()

din unul şi acelaşi fir.

Câmpul OwningThread conţine 0 în cazul secţiunilor critice libere sau identificatorul unic

al firului-posesor.

Page 76: spora

76

Câmpul LockSemaphore este folosit, dacă este necesar să se aştepte până secţiunea critică

este eliberată.

Dacă după un număr de SpinCount ori secţiunea critică nu a fost eliberată, trecem în starea

blocat.

83. Funcţii API pentru secţiunile critice

Funcţiile BOOL InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) şi

BOOL InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection,

DWORD dwSpinCount). După apelare secţiunea critică este gata de lucru.

Funcţia DWORD SetCriticalSectionSpinCount(LPCRITICAL_SECTION

lpCriticalSection, DWORD dwSpinCount) setează valoarea câmpului SpinCount şi returnează

valoarea precedentă a acestuia.

VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) eliberează

resursele, ocupate de secţiunea critică.

VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection), BOOL

TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) permit intrarea în

secţiunea critică. Dacă secţiunea critică este ocupată de un alt fir, atunci ::EnterCriticalSection()

va aştepta până aceasta va fi eliberată, iar ::TryEnterCriticalSection() va returna valoarea

FALSE.

VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) eliberează

secţiunea critică.

84. Clase de secţiuni critice

Pentru o utilizare corectă a secţiunilor critice voi prezenta mai jos codul claselor

secţiunilor critice:

class CLock

{

Page 77: spora

77

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

Page 78: spora

78

};

Clasele CLock şi CAutoLock sunt utilizate, de obicei, pentru sincronizarea accesării

variabilelor clasei, iar CScopeLock este destinat, în special, pentru a fi utilizată în proceduri.

85. Depanarea secţiunilor critice

Depanarea secţiunilor critice este o ocupaţie foarte interesantă, dar şi dificilă. Poţi căuta

ore şi chiar zile în şir cauza apariţiei unei probleme. Erorile, legate de secţiunile critice sunt de

două tipuri: de realizare şi de arhitectură.

Erorile de realizare pot fi depistate relativ uşor şi, de regulă, sunt generate de utilizarea

incorectă (lipsa perechii) a apelurilor ::EnterCriticalSection() şi ::LeaveCriticalSection().

Dintre erorile de arhitectură cea mai frecventă este îmbrăţişarea fatală (deadlock,

v.5.1.3.3), când două fire încearcă să acceseze două şi mai multe secţiuni critice.

Retine studentule:

Secţiunile critice sunt executate relativ repede şi nu cer multe resurse de sistem;

Pentru sincronizarea accesării a mai multor variabile independente este mai bine să fie

utilizate câteva secţiuni critice (nu una pentru toate variabilele);

Codul unei secţiuni critice va fi redus la minimum;

Nu este recomandat să fie apelate metode ale unor obiecte “străine” dintr-o secţiune

critică.

86. Administrarea proceselor. Realizarea excluderii mutuale. Specificarea problemei

Mecanismele care realizează excluderea mutuală pentru un set de programe sunt bazate pe

un principiu comun: utilizarea mecanismului de excludere mutuală existent deja la un nivel

inferior. La nivelul de există două mecanisme elementare: excluderea mutuală la accesarea

unui amplasament de memorie şi masca întreruperilor. Aceste două mecanisme sunt, în

principiu, suficiente pentru toate necesităţile. Dar, din considerente de eficacitate, la nivelul

resurselor fizice sau microprogramelor există dispozitive mai sofisticate, cum ar fi instrucţiunea

Test and Set sau semafoarele.

Page 79: spora

79

Voi preciza mai întâi problema excluderii mutuale. Fie {p1, p2,...,pn} o mulţime de

procese pe care le vom considera ciclice; programul fiecărui proces conţine o secţiune critică.

Excluderea mutuală este asigurată prin două fragmente de program: prolog şi epilog.

Presupunem, că fiecare proces, care intră în secţiunea critică o părăseşte într-un interval de timp

finit.

Soluţia trebuie să posede următoarele proprietăţi:

a) excludere mutuală: la fiecare moment de timp cel mult un proces execută secţiunea

critică,

b) absenţa blocajelor intempestive: dacă în secţiunea critică nu se află vreun

proces, nici un proces nu trebuie să fie blocat de mecanismul excluderii mutuale,

c) toleranţă la defecte: soluţia trebuie să rămână validă şi în cazul unor defecte în

unul sau în mai multe procese, care se află în afara secţiunii critice,

d) absenţa privaţiunilor: un proces, care a cerut intrarea într-o secţiune critică

nu trebuie să aştepte un timp infinit

e) simetrie: prologul şi epilogul trebuie să fie identice pentru toate procesele şi

independente de numărul lor.

Ţinând cont de aceste specificaţii vom construi o soluţie de forma:

<iniţializare> -- comună tuturor proceselor

<programul procesului pi>:

ciclu

<prolog> -- intrare în secţiunea critică

<secţiunea critică>

<epilog> -- ieşire din secţiunea critică

<restul programului>

endciclu

87. Excluderea mutuală prin aşteptare activă

Un proces în aşteptare activă simulează blocarea efectuând o testare repetată a condiţiei

de depăşire, care poate fi actualizată de alte procese. (In calitate de exemplu este Algoritmul lui

Dekker)

88. Algoritmul lui Dekker

Algoritmul lui Dekker ne ajuta sa construim o solutie fără a folosi alte mecanisme de

excludere mutuală, în afară de indivizibilitatea accesării în citire sau actualizarea unui

Page 80: spora

80

amplasament de memorie. Prezint algoritmul pentru două procese, deşi el poate fi extins pentru

un număr arbitrar de procese.

Programul foloseşte trei variabile comune celor două procese:

var c : array [0..1] of boolean;

tur : 0..1;

iniţializare: c[0]:=c[1]:=false;

tur:=0;

prolog : -- pentru procesul i; se va pune j=1-i (celălalt proces)

c[i]:=true;

tur:=j;

test: if c[j] and tur=j then

go to test

endif;

...

epilog : -- pentru procesul i

c[i]:=false;

Aici condiţia de aşteptare e reprezentata printr-o variabilă booleană c , adica c = “un

proces este în secţiunea critică”

Aşteptarea activă poate fi în egală măsură utilizată ca mecanism elementar de sincronizare

în cazul unor alte probleme, diferite de excluderea mutuală.

89. Aşteptarea activă în sisteme multiprocesorale: Test & Set

Instrucţiunea Test And Set (tas), este utilizată în sistemele multiprocesorale, pentru tratarea

cu ajutorul aşteptării active a cazului în care mai multe procese actualizează şi consultă

variabile commune.

Fie m adresa amplasamentului de memorie considerat, sau lacătul, iar R un registru al

procesorului. Prin convenţie, dacă lacătul este în 0, secţiunea critică este liberă, iar dacă este 1 –

ea este ocupată:

tas R, m : <blocare acces la Mp[m]>

Page 81: spora

81

R:=Mp[m]

Mp[m]:=1

<eliberare acces la Mp[m]>

Excluderea mutuală prin aşteptare activă poate fi programată cu ajutorul următoarelor

secvenţe:

iniţializare: stz m -- Mp[m]:=0

prolog : tas R, m

br(R≠0) $-1 -- test iterat

epilog : stz m

90. Semaforul – instrument elementar pentru excluderea mutuală. Definiţii

Un semafor s este constituit prin asocierea unui contor cu valori întregi, notat s.c., şi a

unui fir de aşteptare, notat s.f. si serveşte la blocarea proceselor aşteptând să se producă o

condiţie pentru deblocarea lor; procesele blocate sunt plasate în s.f.

Un procesor poate fi manipulat doar cu ajutorul a două operaţii P(s) şi V(s), numite

primitive.

Fie p un proces care execută P(s) sau V(s), iar q un proces care se află în firul de aşteptare

s.f. Algoritmul primitivelor este următorul:

P(s): V(s):

s.c.:=s.c.-1; s.c.:=s.c.+1;

if s.c.<0 then if s.c.≤0 then

stare(p):=blocat; extragere(q,s.f.);

introducere(p,s.f.) stare(q):=activ

endif endif

Operaţiile introducere şi extragere permit inserarea unui proces într-un fir de aşteptare

sau, respectiv, extragerea.

Doar executarea primitivei P poate bloca un proces, acesta va putea fi deblocat doar de un

alt proces, care a executat primitiva V pe acelaşi semafor.

Page 82: spora

82

91. Semaforul – Proprietăţi

Proprietăţile principale ale sincronizării cu ajutorul semafoarelor pot fi deduse din câteva

relaţii invariante: relaţii verificate iniţial şi relatii care rămân neschimbate după executarea

primitivelor P şi V un număr arbitrar de ori.

1) Fie, pentru un semafor s:

np(s) – numărul total de execuţii a operaţiei P(s),

nv(s) – numărul total de execuţii a operaţiei V(s).

Are loc relaţia: s.c. = s0 – np(s) + nv(s) (1)

deoarece valoarea iniţială a lui s.c. este s0, fiecare operaţie P(s) scade din această valoare o

unitate, iar V(s) adaugă 1.

2) Fie nbloc(s) numărul proceselor blocate în s.f. Are loc relaţia:

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)

3) Relaţia (2) poate fi scrisă sub o altă formă. Fie nf(s) numărul de “treceri” de către

procese a primitivei P(s), adică suma numărului de executări a lui P(s) fără blocare şi a

numărului de deblocări realizate de către V(s). Vom avea în acest caz:

nbloc(s) = np(s) – nf(s).

Introducând această valoare în (21) obţinem:

- nf(s) = max(-np(s), -s.c.-np(s)), sau

nf(s) = min(np(s), s.c.+np(s)).

În fine, utilizând valoarea lui s.c. din (1), avem:

nf(s) = min(np(s), s.c.+nv(s)). (3)

92. Realizarea excluderii mutuale cu ajutorul semafoarelor

Prezint o schemă, care rezolvă problema excluderii mutuale pentru n procese.

iniţializare : semafor mutex init 1

Page 83: spora

83

prolog : P(mutex),

epilog : V(mutex).

Fie nc numărul de procese, care se află în secţiunea critică la un moment concret de timp.

Avem:

nc = nf(mutex) – nv(mutex) (4)

Proprietăţile în cauză pot fi verificate aplicând semaforului mutex relaţia (3) :

nf(mutex) = min(np(mutex), 1+nv(mutex)) (5)

a) Excluderea mutuală

Din (5) avem:

nf(mutex) ≤ 1+nv(mutex)

şi, utilizând (4), obţinem nc ≤ 1: excluderea mutuală este asigurată.

b) Absenţa blocajelor

Presupunem, că nici un proces nu se află în secţiunea critică. Vom avea în acest caz nc = 0,

sau

nf(mutex) = nv(mutex) sau încă

nf(mutex) ≤ 1+nv(mutex)

Vom avea conform relaţiei (5):

nf(mutex) = np(mutex) sau

nbloc(mutex) = 0

1). Secţiuni critice incorporate. Blocaje

Voi considera două procese p şi q pentru care programul conţine două secţiuni critice

distincte, corespunzătoare utilizării a două resurse critice distincte.

procesul p procesul q

... ...

(1) P(mutex1) (11) P(mutex2)

... ...

(2) P(mutex2) (21) P(mutex1)

... ...

Page 84: spora

84

V(mutex2) V(mutex1)

... ...

V(mutex1) V(mutex2)

Dacă traiectoria temporală de execuţie a proceselor p şi q începe cu (1, 11, 2, 2

1), se va

ajunge la o situaţie în care ambele procese sunt blocate pentru un timp infinit, deoarece fiecare

dintre procese poate fi deblocat doar de către celălalt. Această situaţie este numită

2). Aşteptare infinită în secţiunea critică sau impas

Validitatea soluţiei propuse se bazează pe presupunerea, că toate procesele părăsesc

secţiunea critică în timp finit. Dar pot fi şi cauze, care conduc la o aşteptare infinită. Astfel,

blocarea, incorectitudini sau ciclări infinite într-un proces, care se află în secţiunea critică, pot

paraliza toate procesele concurente cu procesul dat. În cazul unor secţiuni critice globale (care

prezintă interes pentru toţi utilizatorii), realizate pentru un sistem de operare, pot fi propuse

următoarele soluţii:

oricărui proces, care execută o secţiune critică globală, i se atribuie, pe toată durata

acestei execuţii, un statut special, care îi conferă anumite drepturi particulare: prioritate

înaltă, protecţie contra distrugerii, etc.

un orologiu de gardă este armat la intrarea unui proces în secţiunea critică; dacă

procesul nu părăseşte secţiunea critică după un interval de timp predefinit, sistemul de

operare forţează ieşirea procesului şi eliberează astfel secţiunea critică. Această soluţie nu

este cea mai bună, or datele globale, manipulate în secţiunea critică, pot să devină

incoerente. Este necesar să se ofere posibilitatea restabilirii acestor date la o stare

anterioară, considerată validă, ceea ce implică salvări periodice.

3). Privaţiune

Algoritmul excluderii mutuale garantează intrarea exact a unui proces în secţiunea critică,

dacă mai multe procese încearcă acest lucru, când secţiunea critică este liberă. Se poate

întâmpla ca un proces particular să fie reţinut pentru un interval de timp nedefinit: acest

fenomen se numeşte privaţiune.

93. Funcţionarea şi structura unui nucleu de sincronizare. Stările unui proces. Fire

de aşteptare

Page 85: spora

85

Noţiunea de proces şi operaţiile asociate sunt implementate cu ajutorul unor programe

şi/sau microprograme, care formează nucleul de administrare a proceselor. În cadrul descrierii

unui sistem de operare cu ajutorul maşinilor abstracte ierarhice , nucleul constituie nivelul cel

mai inferior, realizat direct pe maşina fizică. Maşina abstractă, realizată astfel poate fi numită o

maşină a proceselor, care posedă, în afara setului de instrucţiuni de bază, primitivele care

permit crearea, distrugerea şi sincronizarea proceselor. Ca şi orice maşină abstractă, maşina

realizată în acest mod ascunde unele proprietăţi ale maşinii fizice. Astfel:

noţiunea 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 numărul procesoarelor nu intervine decât doar asupra

performanţelor 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 specificaţiile maşinii fizice

(gestiunea întreruperilor, structura cuvântului de stare, sistem mono- sau multiprocesoral, etc.)

şi de specificaţiile maşinii abstracte care trebuie realizate, îndeosebi de mecanismul de

sincronizare ales.

Stările unui proces

Am considerat până acuma că un proces se poate afla în două stări: activ sau blocat.

Luarea în consideraţie a alocării fizice a unui procesor ne impune să descompunem starea

activă în două stări noi. Un proces activ se numeşte ales, dacă el este în curs de execuţie pe un

procesor fizic; el se numeşte eligibil dacă nu poate fi executat din cauza lipsei unui procesor

disponibil. Figura 4.1 descrie stările unui proces şi tranziţiile lui.

Tranziţiile 3 şi 4 (blocare şi deblocare) sunt tranziţiile “interne”, datorate sincronizării

proceselor. Tranziţiile “tehnologice” 1 şi 2 sunt datorate alocării procesoarelor fizice

proceselor.

eligibil

(ready

ales

(exe)

blocat

(wait)

(1)

(2)

(3) (4)

Fig.4.1. Stările unui proces

Page 86: spora

86

Fire de aşteptare

Administrarea proceselor face apel la fire de aşteptare. Astfel, fiecărei cauze distincte de

blocare (semafor, condiţie într-un monitor, etc.) i se asociază un fir de aşteptare pentru a stabili

o ordine a proceselor blocate.

Mulţimea programelor, care realizează aceşti algoritmi se numeşte planificator .

Programul, care realizează alegerea propriu-zisă se numeşte dispecer. Schema generală a

firelor de aşteptare ale proceselor este prezentată în fig.4.2. Deplasarea proceselor între aceste

fire corespunde schimbării stării.

94. Administrarea contextelor şi schemele primitivelor

1) Conţinutul contextului

Operaţia de alocare a procesorului fizic impune păstrarea pentru fiecare proces a unei copii

a contextului. Această copie a contextului descrie starea procesorului pentru procesul

considerat. În acest scop fiecărui proces i se asociază o mulţime de informaţii rezidente în

firul proceselor eligibile

fire de procese

blocate

planificator

dispecer proces ales

Fig.4.2. Fire de aşteptare ale proceselor, administrate de nucleul sistemului de operare

Page 87: spora

87

memorie şi numită vector de stare, bloc de control al procesului sau blocul contextului, care

conţine:

informaţiile despre starea procesorului, necesare la realocarea lui (conţinutul

cuvântului de stare, registrelor),

valorile atributelor procesului (prioritate, drept de acces),

pointeri la spaţiul de lucru al procesului (segmentele procedură şi date, stiva de

execuţie),

informaţii de gestiune (starea, legăturile de înlănţuire).

2) Organizarea nucleului

Execuţia programelor nucleului este declanşată în două moduri (fig.4.3):

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 operaţii de sincronizare şi sunt invizibile la

nivelurile superioare.

Programul unei primitive a nucleului are următoarea schemă generală:

prolog; -- salvarea contextului şi intrarea în secţiunea critică

control; -- verificarea drepturilor şi a parametrilor

<corpul programului> -- manipulează firele proceselor

alocare_procesor; -- programul dispecer şi ieşirea din secţiunea critică

Tratarea întreruperilor de către 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 aşteptarea unei întreruperi anume, existând pentru aceasta

o instrucţiune specială.

întreruperi

alocare procesor apelare supervizor

lansare

periferice,

ceasul

programul

nucleului

proces

Fig.4.3. Comunicarea cu un nucleu de sincronizare

Page 88: spora

88

2) Asocierea unei operaţii de deblocare la o întrerupere.

95. Realizarea unui nucleu de sincronizare. Organizarea general

96. Realizarea unui nucleu de sincronizare. Interfeţele

a) Gestionarea proceselor

Procesele pot fi create şi distruse în mod dinamic, şi sunt organizate ierarhic conform

relaţiei de legătură (v.3.5). Un proces este creat cu ajutorul primitivei:

creare(p, context iniţial, atribute)

Atributele unui proces conţin prioritatea şi drepturile de a executa anumite operaţii.

Contextul iniţial specifică starea iniţială a cuvântului de stare şi a registrelor procesorului, şi a

spaţiului de lucru asociat procesului. Procesul este creat în starea eligibil. Numărul său p

(numele) este returnat ca rezultat (valoarea nil, dacă crearea este imposibilă). O funcţie

determină_număr_propriu permite unui proces să afle numărul său propriu.

Primitivele care urmează pot fi aplicate unui proces existent şi pot fi executate doar de

procesul-părinte.

Procedura distrugere poate fi utilizată de către un proces pentru a se autodistruge. Deci,

distrugere(p) va distruge toate procesele desemnate de procesul p şi toţi descendenţii acestora.

Procedura suspendare(p) întrerupe execuţia unui proces p, plasându-l într-un fir de

aşteptare special. Execuţia 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 către procesul-părinte.

Utilizarea primitivelor creare, distrugere, suspendare şi reluare este condiţionată 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 condiţii.

97. Realizarea unui nucleu de sincronizare. Structuri şi algoritmi

Din momentul creării sale unui proces i se asociază un număr fix (process handler), care

serveşte la desemnarea lui şi permite accesarea blocului său de context. Blocul de context

conţine următoarele câmpuri:

Page 89: spora

89

Csp : zona de salvare a cuvântului de stare a procesorului,

Reg : zona de salvare a registrelor generale ale procesorului,

Stare : valoarea stării procesului (eligibil, blocat, ...),

Prio : prioritatea procesului,

Drepturi : drepturile procesului,

Fire, etc. : legături de înlănţuire în ierarhia proceselor,

Suc, etc. : legături de înlănţuire în firele de aşteptare (FA).

Administrarea proceselor utilizează fire de aşteptare, ordonate în ordinea de descreştere a

priorităţilor şi comandate de un set de proceduri de accesare, specificate mai jos (p specifică un

proces, f – un fir de aşteptare):

introducere(p, f) Introduce p în f, în elementul lui f care corespunde

priorităţii procesului şi în ordinea sosirii pentru procesele cu aceeaşi prioritate.

primul(f) Întoarce numărul (numele) procesului din vârful lui f (nil dacă f este

vid); nu modifică f.

ieşire(p, f) Extrage din firul f primul proces, numărul acestuia fiind pus în p (nil

dacă f este vid).

extragere(p, f) Extrage din firul f procesul cu numărul 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) Funcţie booleană cu valoarea adevărat, dacă firul f este vid, fals în caz contrar.

Page 90: spora

90

98. Realizarea unui nucleu de sincronizare. Realizarea monitoarelor

1) Semantica primitivei semnalizare. Specificarea iniţială a primitivei c.semnalizare

precizează că unul din procesele care sunt în aşteptarea condiţiei c (dacă există) este imediat

deblocat, ceea ce implică trecerea temporară în starea blocat a procesului care execută

semnalizare. În specificarea prezentă procesul deblocat este simplu trecut în starea eligibil şi

trebuie să intre în monitor; el se află, deci, în competiţie cu alte procese, care aşteaptă să intre în

monitor, şi nu este garantat că va fi imediat ales. Condiţia, care provocase deblocarea, poate fi

modificată înainte ca procesul deblocat să-şi reia execuţia în monitor. Pentru această nouă

interpretare trebuie să fie modificată forma punerii în aşteptare. O construcţie de forma

if continuare_non_posibilă then

c.aşteptare

endif

devine în acest caz

while continuare_non_posibilă do

c.aşteptare

endwhile

2) Deblocare multiplă. Problema deblocării multiple poate fi rezolvată uşor

introducând o primitivă nouă c.difuzare_semnal efectul căreia se exprimă astfel:

while c.non_vid do

c.semnalizare

endwhile

Fiind dat, că toate procesele deblocate vor testa din nou condiţia şi cer din nou acces la

monitor, această primitivă va avea evident efectul aşteptat.

3) Întârziere de gardă. Din probleme de securitate, în special pentru tratarea

blocajelor, poate fi util să se asocieze o întârziere de gardă condiţiei unui monitor. Această

întârziere este egală cu durata maximă de blocare a unui proces într-un fir de aşteptare asociat

condiţiei date. La expirarea întârzierii de gardă va fi efectuată o tratare specificată. Această

tratare poate consta în simpla deblocare a procesului (care va testa din nou condiţia de depăşire)

sau transferul său într-un fir de aşteptare special (v.4.3.2.3).

Page 91: spora

91

Fie M.c.întârziere întârzierea de gardă asociată unei condiţii c în monitorul M. Se

presupune disponibil un ceas habs, care pune la dispoziţie timpul absolut. Trebuie să adăugăm în

programul primitivei c.semnalizare instrucţiunea următoare:

hdeblocare[p]:=habs+M.c.întârziere

unde hdeblocare[p] este un câmp nou al blocului de context al procesului p. Un proces, numit

“gardian”, deblocat la intervale regulate de timp parcurge mulţimea contextelor şi efectuează

tratamentul specificat proceselor pentru care hdeblocare[p]>habs.

99. Realizarea unui nucleu de sincronizare. Algoritmi de bază

Programul monitorului trebuie să asigure două funcţii:

excluderea mutuală pentru procedurile monitorului,

blocarea şi deblocarea asociate primitivelor aşteptare şi semnalizare.

Fiecărui monitor M îi sunt asociate următoarele structuri de date:

un dispozitiv de excludere mutuală M.disp (lacăt), care poate lua două valori liber

şi ocupat, şi un fir de aşteptare M.fir asociat acestui dispozitiv. Iniţial M.disp=liber,

M.fir=<vid>.

fiecărei condiţii c de M îi este asociat un fir M.c.fir, un contor de gardă

M.c.întârziere şi, pentru condiţiile asociate unei întreruperi, un indicator boolean

M.c.într_sosită.

Firul proceselor eligibile este determinat de f_eligibil.

Pentru un monitor M vom cerceta programul a patru secvenţe intrare, ieşire, c.aşteptare şi

c.semnalizare (secvenţele intrare şi ieşire sunt inserate de compilator şi încadrează execuţia

procedurilor externe ale monitorului). Să definim mai întâi procedurile de gestiune a

dispozitivului:

cerere_disp(M, p): eliberare_disp(M):

if M.disp=ocupat then if vid(M.fir) then

intrare(p, M.fir); M.disp:=liber

stare[p]:=blocat else

else ieşire(q, M.fir);

M.disp := ocupat; intrare(q, f_eligibil);

intrare(p, f_eligibil); stare[q]:=eligibil

stare[p]:=eligibil endif

Page 92: spora

92

endif

Cele patru secvenţe se vor scrie utilizând următoarele proceduri:

intrare(M): ieşire(M):

prolog; prolog;

p:=<proces apelant>; p:=<proces apelant>;

cerere_disp(M, p); eliberare_disp(M);

alocare_procesor; intrare(p, f_eligibil);

alocare_procesor;

c.aşteptare: 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; ieşire(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;

100. Realizarea unui nucleu de sincronizare. Tratarea întreruperilor

Pentru asigurarea uniformităţii mecanismelor de sincronizare fiecărei întreruperi i se

asociază:

o condiţie într-un monitor,

un proces ciclic care realizează tratarea întreruperilor, în stare de repaus acest

proces este în aşteptarea condiţiei.

O condiţie poate fi asociată unui singur nivel de întrerupere. Sosirea unei întreruperi

provoacă executarea funcţiei semnalizare pentru condiţia asociată. Prioritatea relativă a

întreruperilor este tradusă în prioritatea proceselor, care tratează întreruperile.

Page 93: spora

93

Mecanismul descris mai sus nu este absolut perfect. De exemplu, excluderea procedurilor

monitorului nu poate fi aplicată întreruperilor. Se poate întâmpla ca o întrerupere să fie cerută

atunci când 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.aşteptare; -- evitarea pierderii unei întreruperi

go to test

endif;

<tratarea întreruperii>

endciclu

<sosirea unei întreruperi asociate lui M.c>

M.c.într_sosită := true;

c.semnalizare;