Sunteți pe pagina 1din 29

29

Capitolul 3 Gestiunea proceselor si a procesoarelor


Capitolul de fata abordeaza o serie de probleme legate de planificarea job-urilor si a proceselor (in sisteme mono- si multi-procesor), precum si de sincronizare intre procese. Sint ilustrate si citeva solutii de rezolvare a blocajului reciproc intre mai multe procese. Capitolul se incheie cu descrierea mecanismului de planificare de procese in Unix. Sint punctate deasemenea si principalele posibilitati de sincronizare si comunicare intre procese. Notiuni de baza Planificarea de job-uri Planificarea de procese. Comparatie intre sistemele de operare in timp partajat si sistemele de operare in timp real Interactiunea si sincronizarea proceselor. Mecanismul Producator-Consumator Resurse. Deadlock Sisteme multiprocesor Gestiunea proceselor in Unix. Sincronizare. Comunicatie job, proces, procesor, SO in timp partajat, SO in timp real, interactiunea si sincronizarea proceselor, mecanismul Producator-Consumator, resurse, deadlock, sisteme multiprocesor

Obiective

Continut

Cuvinte cheie:

Modul1 Notiuni de baza


In continuare vor fi listate cite notiuni fundamentale referitoare la terminologia folosita si la notiunile conexe fenomenelor descrise: Program= un ansamblu ordonat de instructiuni; Instructiune= o operatie elementara executata de catre procesor, indivizibila (in sensul ca executia ei de catre un procesor nu poate fi intrerupta); Proces= o entitate dinamica reprezentind un program in stare de executie, alcatuita din: zone de cod, cum ar fi: programul principal, procedurile sau functiile; zone de date: zone care contin declaratiile si definitiile datelor folosite; resurse alocate procesului, care, desigur, sint variabile in timp; informatii utile pentru evaluarea starii procesului - de exemplu, numele procesului, starea sa, continutul registrilor procesorului si altele. Toate acestea pot fi privite ca programul propriu-zis alaturi de contextul sau de lucru (toate informatiile externe programului necesare evolutiei procesului corespunzator).

Vector de stare - pentru a putea administra procesele existente, SO trebuie sa pastreze o imagine a fiecarui proces (care sa contina informatiile de mai sus referitoare la procesul respectie), in orice moment de timp - aceasta imagine se numeste vector de stare al procesului. Starile unui proces - principalele stari in care se poate afla un proces sint: pregatit pentru executie, in executie sau in asteptare.

30

Fig.14. Starile principale ale unui proces intr-un SC Un proces se afla in starea pregatit pentru executie (ready) cind are alocate toate resursele, mai putin procesorul. El poate parasi acesta stare numai atunci cind i se aloca si procesorul (eliberat intre timp), moment in care trece in starea in executie (running). Din aceasta stare, un proces se poate intoarce in starea pregatit pentru executie la prelevarea fortata a procesorului. Deasemenea, el poate intra in starea in asteptare (blocked) daca este nevoit sa astepte producerea unui eveniment cum ar fi: sfirsitul unei operatii de I/O, aducerea unei pagini de pe disc, eliberarea unor resurse de care are nevoie etc. Ar mai trebui metionat ca atit timp cit procesul se afla in aceasta stare, i se pot dealoca unele resurse spre a fi date altor procese! Administrarea proceselor la nivelul SO presupune:

pastrarea unei evidente a starii curente a tuturor proceselor din sistem; schimbarea starii proceselor ori de cite ori este nevoie.

Ea este sustinuta de 3 liste existente la nivelul sistemului:


lista proceselor active (in rulare); lista proceselor blocate (in asteptare); lista proceselor intrerupte (pregatite pentru rulare).

Fig.15. Listele cu starile proceselor Crearea unui proces se face in timpul executiei unei lucrari si consta in constructia unui vector de stare si initializarea lui; inregistrarea vectorului de stare intabela de procese si in lista corespunzatoare;

Un proces este creat la initiativa altui proces utilizator sau sistem, numit proces tata. Toate procesele din sistem formeaza o arborescenta cu o radacina unica. Distrugerea unui proces consta in:

stergerea tuturor informatiilor despre el; eliberarea tuturor resurselor alocate lui.

Ea se poate face:

la sfirsitul executiei sale (autodistrugere);

31

la initiativa altui proces utilizator sau sistem (terminare normala) - de exemplu, in cazul in care el functioneaza defectuos.

In momentul distrugerii unui proces, creatorul sau este acela care va trebuie sa distruga si toate procesele sale descendente. Gestiunea proceselor se face pe 2 niveluri:
pe termen mediu (planificarea de job-uri sau lucrari): consta in alegerea dintre toate job-urile prezentate a aceluia pentru care se va crea un proces; ea are prioritate mica la nivelul sistemului; pe termen scurt (planificarea de procese): care consta in a da de lucru procesorului ori de cite ori este liber; ea are prioritate mare.

32

Modul2 - Planificarea de job-uri


In acest modul vor fi prezentate mai intii citeva consideratii legate de functiile componentei de gestiune a job-urilor, in continuare fiind descrisi citiva algoritmi de mono-programare. In final, este prezentat si un algoritm de multi-programare. Sa incepem cu consideratiile privind sarcinile subsitemului de administrare a job-urilor: SR. Pentru a tine gestiunea job-urilor, la nivelul SO, exista cite un bloc de control al fiecarui job (JCB - Job Control Block) - toate aceste JCB-uri se afla in tabela de job-uri a sistemului. Un JCB contine identificatorul job-ului, timpul estimativ de executie, starea in care se gaseste acesta, memoria ocupata precum si prioritatea sa la nivelul sistemului. PA. Politica implementata de planificator se bazeaza pe:

disponibilitatea resurselor; cost ridicat pentru servicii prioritare; durata job-ului (se acorda, de exemplu, prioritate mare job-urilor scurte); echilibrul sistemului (intreteserea job-urilor limitate UCP cu cele limitate I/O; garantarea serviciilor (SO trebuie sa asigure executia oricarui job); garantarea termenelor (SO trebuie sa ruleze orice job intr-un anumit timp; dealtfel prioritatea job-urilor trebuie sa creasca prin imbatrinire).

Algoritmi de planificare de job-uri Pentru a intelege mai bine cum functioneaza algoritmii prezentati, ei vor fi descrisi pe un exemplu concret. Fie asadar urmatorul exemplu: presupunem ca vor fi supuse SO, spre executie, 3 job-uri, caracterizate de urmatorii timpi de sosire, respectiv executie: Numar 1 2 3 Nota Tsosire 10 10.10 10.25 Trulare 2 1 0.25

Timpii se dau in fractiuni de ore.

Daca presupunem ca sistemul lucreaza in mono-programare, sub diverse politici de planificare avem, respectiv, urmatoarele rezultate: FIFO (First In First Out) Numar Tsosire Tinceput 1 10 10 2 10.10 12 3 10.25 13 Nota Tterminare 12 13 13.25 Traspuns 2 2.9 3

Traspuns= Tterminare-Tsosire.

33

SXFS (Shortest eXecution First Service) Numar Tsosire Tinceput Tterminare 1 10 10 12 2 10.10 12.25 13.25 3 10.25 12 12.25

Traspuns 2 3.15 2

Daca se aplica o varianta a tehnicii de mai sus, in sensul ca sint asteptate toate job-urile inainte de alua o decizie, se obtin urmatoarele rezultate: SXFS(2) Numar 1 2 3 Tsosire 10 10.10 10.25 Tinceput 11.5 10.5 10.25 Tterminare 13.5 11.5 10.5 Traspuns 3.5 1.4 0.25

Pentru a putea evalua diversii algoritmi folositi, s-a calculat initial indicatorul numit timp de raspuns - o analiza mai profunda a evolutiei sale, vizavi de comportamentul general al sistemului, a condus la concluzia ca el nu descrie corect functionarea sistemului. Ca urmare s-a trecut la calcularea unui al doilea indicator, numit timp de raspuns ponderat, care se calculeaza astfel: wi=Traspuns/Trulare_in_monoprogramare= =(Tterminare - Tsosire)/(Tterminare - Tinceput). Pentru exemplul considerat valorile pentru timpul de raspuns ponderat sint: wi/FIFO 1 2.9 12 wi/SXFS(1) 1 3.15 8
n

wi/SXFS(2) 1.75 1.4 1


n

In continuare, pentru a ilustra functionarea sistemului, s-au calculat niste medii si anume: T= i =1

Traspunsi n

, respectiv w= i =1 n

wi

Pentru exemplul de mai sus s-au obtinut valorile: Strategia FIFO SXFS(1) SXFS(2) T 2.63 2.38 1.72 w 5.3 4.5 1.38

In cazul acestui exemplu, se observa ca atit T cit si w scad, ceea ce indica imbunatatirea performantelor din punctul de vedere al sistemului.

34

Sa consideram acum un alt exemplu, pe care sa-l analizam atit in mono-programare folosind algoritmul FIFO, cit si in multi-programare. Mono-programare/FIFO: Numar Tsosire Trulare 1 10 0.3 2 10.2 0.5 3 10.4 0.1 4 10.5 0.4 5 10.8 0.1 Tinceput 10 10.3 10.8 10.9 11.3 Tterminare 10.3 10.8 10.9 11.3 11.4 Traspuns 0.3 0.6 0.5 0.8 0.6 Traspuns_ponderat 1 1.2 5 2 6

Fig.16. Monoprogramare vs. multiprogramare Multi-programare Numar Tsosire 1 10 2 10.2 3 10.4 4 10.5 5 10.8 Trulare 0.3 0.5 0.1 0.4 0.1 Tinceput 10 10.2 10.5 10.6 10.9 Tterminare 10.4 11.3 10.6 11.4 11.0 Traspuns 0.4 1.2 0.2 0.9 0.3 Traspuns_ponderat 1.33 2.4 2 2.25 3

35

Observati e

Pentru multi-programare, s-a presupus ca: operatiile de I/O nu se suprapun cu cele de calcul; resursele sint nelimitate; multi-programarea se face FIFO (procesele primesc procesorul pentru o cuanta dt dupa care se asaza din nou la coada la el): Desigur ca in analizarea unei situatii reale trebuie sa se tina cont de toate aceste elemente!

Daca se calculeaza acum cei doi indicatori T si w pentru ambele situatii se obtin valorile: Strategie Mono/FIFO Multi/FIFO Observati e T 0.56 0.6 w 3.04 2.19

Se observa aici ca T fluctueaza, in sensul ca el creste, desi performantele globale ale sistemului au crescut - acesta este motivul concret petru care s-a trecut la folosirea lui w ca indicator pentru evolutia sistemului.

Modul3 Planificarea de procese


In continuare sint considerate citeva aspecte referitoare la sarcinile modulului de gestiune a proceselor: SR. In vederea gestionarii proceselor, SO va mentine o structura de date asociata fiecarui proces numita bloc de control al procesului (Proces Control Block) care este totuna cu vectorul de stare al procesului. Diferitele stari in care se gasesc procesele sint inlantuite in listele corespunzatoare, inserarea facindu-se conform politicii de alocare utilizate (listele sint ordonate conform acestei politici). PA. Politici de alocare posibile pentru procese sint:
Round-Robin:

procesele pregatite pentru executie sint organizate intr-o coada la procesor - cind acesta se elibereaza, primul proces din coada va primi procesorul pentru o cuanta de timp dt; daca dupa expirarea cuantei de timp, procesul inca nu s-a terminat, el va fi trecut din nou in coada, in ultima pozitie;

Fig.17. Round-Robin simplu


Round-Robin

limitat: procesele nou venite sint introduse in coada principala de procese care asteapta la UCP numai pentru k treceri - daca nu se termina in k treceri, ele vor fi trecute intr-o coada secundara, de unde se iau cind nu mai este nici-un proces in coada principala; Round-Robin pe mai multe niveluri, cu reactie inversa: procesele nou venite vor fi inserate in prima coada - daca ele nu se termina in k1 cuante, ele vor fi trecute in coada

36

a 2-a samd. Cind in coada intii nu mai este nici-un proces, se va trece la aplicarea unui Round-Robin simplu in coada a 2-a, samd. Daca un anumit timp tau nu s-a facut nici-o planificare in coada i , primul proces din aceasta coada este promovat ultimul in coada i-1 (imbatrinirea proceselor le creste prioritatea);

Fig.18. Round-Robin pe mai multe niveluri


Round-Robin

invers cu restul ramas din cuanta de timp: procesul curent primeste procesorul pentru o cuanta de timp dt - daca in timpul acesteia el face o operatie de I/O, atunci i se va lua procesorul (ca si in cazul Round-Robin-ului simplu), numai ca nu va fi inserat la sfirsitul cozii, ci intr-o pozitie invers proportionala cu partea ramasa din cuanta de timp - adica, daca i-a ramas , de exemplu, 75% din cuanta de timp, el va fi inserat la 25% (din lungimea cozii) "distanta" de procesor;

Fig.19. Round-Robin invers cu restul de timp ramas


dupa

prioritati, care poti sa fie fixe sau variabile in timp (functie de resurse si de comportamentul job-ului); conforme cu echilibrul sistemului (cuantificat ca gradul de utilizare al UCP si al EP); politici favorizind procesele interactive (pentru impresia lasata utilizatorului, desigur :o))); politici corespunzatoare proprietatilor job-ului caruia ii apartine procesul. De obicei, politica de alocare a unui SO este reprezentata cu ajutorul unei diagrame de stare. Un exemplu in acest sens se afla in figura urmatoare:

Fig.20. Exemplu de diagrama de stare O incercare de citire a acestei diagrame ne arata ca SO folosit:
favorizeaza

procesele interactive (dind prioritate mare proceselor blocate, care asteapta o intrare de la terminal, la terminarea operatiei de intrare de la terminal); incearca sa faca transparenta pentru utilizator lipsa paginii (dind prioritate mare proceselor la iesirea din starea "blocat pentru lipsa de pagina"); incearca sa realizeze echilibrul sistemului dind prioritate mica si cuante mari joburilor limitate UCP. Observati e In ceea ce priveste politicile de planificare pentru executie, exista si in acest caz o puternica formalizare cu ajutorului unui model matematic (cunoscut sub numele de modelul Markov).

37

Comparatie intre SO in timp partajat si SO in timp real Din punct de vedere al planificarii proceselor pentru executie, SO pot fi, in principal, in timp partajat (time-sharing) sau in timp real (real time). In continuare se va face o scurta comparatie a celor doua clase de sisteme, dupa diverse criterii de comparatie:
1.

Planificarea pentru executie se face, pentru ambele clase de sisteme (timp real - TR, timp partajat - TP), functie de prioritati, dar prioritatile sint: TR: fixate de utilizator, rolul SO in modificarea lor fiind nul (evident, se va acorda prioritate mare proceselor al caror timp de raspuns este critic - de exemplu, cresterea presiunii peste o anumita limita intr-un recipient care poate exploda in cazul in care aceasta nu este redusa rapid); TP: calculate dinamic de catre sistem, in functie de obiectivele sale; Momentul planificarii este stabilit diferit astfel: TR: planificarea pentru executie este declansata de evenimente (din acest motiv aceste sisteme sint cunoscute sub numele de SO conduse de evenimente; TP: in acest caz, ceasul sistemului este acela care declanseaza planificarea pentru executie, fie la expirarea cuantei de timp, fie la realizarea unei operatii de I/O; Alocarea resurselor se face, indiferent de tipul SO, astfel incit performantele sa fie optimizate, insa elementul de referinta este diferit in functie de felul SO, astfel: TR: optimizarea se face in raport cu un utilizator (proces) individual; TP: optimizarea este globala, la nivelul intregului SO;

2.

3.

4. Prelevarea fortata functioneaza in ambele sisteme, insa ea actioneaza diferit astfel:


a.

Prelevarea fortata a procesorului se face: TR: la aparitia unui proces de prioritate mai mare; TP: la sfirsitul cuantei alocate sau la realizarea unei operatii de I/O; Prelevarea fortata a celorlalte resurse se face diferit in cele doua feluri de SO, dupa cum urmeaza: TR: deoarece in aceste sisteme viteza de acaparare a resurselor este importanta, un proces care pierde procesorul nu va pierde si celelate resurse (deoarece el ar trebui sa lupte pentru mai multe ca sa intre din nou in executie; TP: viteza de alocare a resurselor nefiind critica din punctul de vedere al sistemului, un proces care pierde procesorul va pierde si celelalte resurse;

b.

5. Viteza operatiilor de I/O:

38

TR: este importanta in acest caz, ea trebuind sa fie mare. Pentru a se realiza acest obiectiv, operatiile de I/O vor fi declansate asincron fata de task-ul care le solicita (adica ele vor fi lansat anticipat, astfel ca atunci cind ele sint necesare pot fi gasite deja in buffer-ele SO; TP: nu este critica din punctul de vedere al SO;

6. Protectia este importanta in ambele clase de sisteme, insa:


TR: in acest caz, ea devine esentiala, deoarece procesele cu prioritate mare pot acapara resurse pe care sa nu le mai elibereze niciodata! TP: prelevarea fortata reuseste sa o asigure integral in aceast tip de SO.

Modul4 - Interactiunea si sincronizarea proceselor


In cadrul unui SC interactiunea proceselor are loc in doua directii: concurenta pentru acapararea resurselor; cooperarea pentru realizarea unui scop comun. O notiune strins legata de cea de interactiune a proceselor este sincronizarea. Aceasta consta in controlul vitezei cu care se desfasoara procesele, adica in oprirea unui anumit proces asteptind ca altul sa ajunga intr-un anumit punct. In principiu problema sincronizarii se pune in doua situatii posibile: privind folosirea resurselor: de exemplu, fie un sistem in care, in memoria interna, se afla incarcate doua procese Pr1 si Pr2, care, fiecare, va avea nevoie de imprimanta la un moment dat, astfel: Pr1 cere imprimanta, care libera fiind, ii este acordata; Pr2 solicita ulterior si el imprimanta si va fi blocat pina la eliberarea ei. In competitia pentru acaparea resurselor (in cazul acestui exemplu, imprimanta), SO trebuie sa marcheze 4 momente importante: cererea/asteptarea/utilizarea/eliberarea resursei; referitor la gestiunea mesajelor: si in acest caz, mecanismul de utilizare a "resursei" (in acest caz buffer-ul prin care are loc transferul mesajului de la un proces la celalalt) este asemanator, marcind cele patru momente precizate mai sus.

Putem conchide ca cele doua tipuri de interactiuni nu sint fundamental diferite, in sensul ca, in primul caz, imprimanta este caracterizata de o variabila booleana care descrie starea ei (libera sau ocupata), iar in cel de-al doilea, situatia buffer-uului intermediar este gestionata tot cu ajutorul unei astfel de variabile. In concluzie, putem spuna ca interactiunea proceselor poate fi vazuta ca abilitatea acestora de a utiliza in comun variabile (la care, evident, mai multe procese pot face acces concurent). In continuare vor fi prezentate diverse solutii de "modelare" acestei interactiuni in sistemele de operare. Pentru inceput sa presupunem cazul unui sistem multiprogramare cu planificare omogena, in care exista mai multe procesoare disponibile la un moment dat, dupa cum se poate vedea in figura urmatoare:

39

Fig.21. Sistem multiprocesor cu planificare omogena In momentul in care unul dintre procesoare se va elibera, fie el Pi, el va realiza urmatoarele actiuni: . salveaza starea procesului rulat anterior; . noteaza valoarea lui "n"; . incrementeaza valoarea lui "n"; . marcheaza procesul "n" ca fiind "in rulare", ca sa nu-l mai executa si alte procesoare; . incarca registrii procesului "n" si-l executa.

Sa ne imaginam acum ce se va intimpla daca doua procesoare (fie ele Pi si Pj) se elibereaza simultan - in acest caz, va avea loc o intretesere a operatiilor astfel: Pi Pj Pi Pj ... Pi Pj Evident o astfel de functionare este de nedorit, deoarece acelasi proces va fi rulat de doua ori pe doua procesoare diferite. Devine evident ca trebuie realizat un mecanism de sincronizare care sa preintimpine astfel de situatii. Practic trebuie asigurata excluderea mutuala privind accesul la anumite variabile, adica, daca un proces acceseaza variabila respectiva, nici-un altul nu va putea sa faca acelasi lucru. Prima solutie de implementare a excluderii mutuale la nivelul SO a fost "asteptarea ocupata". In acest caz, daca un proces face acces la anumite structuri de date, toate celelalte procese vor fi oprite s-o faca, ele ciclind pina la eliberarea structurilor de date respective. Este clar ca o astfel de rezolvare a problemei este ineficienta, deoarece ciclarea presupune ocuparea procesorului. Concret, asteptarea ocupata se realizeaza prin "zavorirea" structurilor de date utilizate in comun, adica prin asocierea cu fiecare astfel de structura a unei variabile booleene de tip zavor, fie ea z - daca z=0 atunci inseamna ca resursa (careia ii este asociata structura de date respectiva) este libera, iar daca z=1 inseamna ca este ocupata. Algoritmul de functionare a zavorului este urmatorul:

Fig.22. Algoritm de zavorire

40

Pentru a evita functionari defectuoase de tipul celei din exemplul precedent, se impune ca operatia de testare si setare a zavorului (TAS) sa fie neintreruptibila. O a doua solutie de realizare a excluderii mutuale, care evita asteptarea ocupata, s-au introdus in nucleul SO doua proceduri: WAIT(z): daca zavorul z este blocat atunci SO blocheaza procesul si-l pune in coada la zavorul z

SIGNAL(z): daca resursa se elibereaza atunci SO extrage primul proces din coada de asteptare si-i aloca resursa Astfel, secventele de lucru cu zavorul devin: LOCK(z): *examinare z *setare z1 daca zinitial=1 atunci WAIT(z) UNLOCK(z): *resetare z0 *SIGNAL(z) O a treia solutie folosita corespunde sistemelor in care exista mai multe resurse de acelasi tip. In acest caz, se folosesc asa numitele semafoare numaratoare (introduse de Dijkstra in 1965) - aceastea constau dintr-o valoare a semaforului v(s) - constind in numarul de resurse de acelasi tip - si o coada la acesta c(s). Pentru manipularea acestor semafoare au fost concepute doua primitive: P(s), care corespunde cererii de resursa, si V(s), corespunzind eliberarii acesteia: P(s): v(s)v(s)-1 daca v(s)<0 atunci WAIT(s) V(s): v(s) v(s)+1 daca v(s) 0 atunci SIGNAL(s)

41

unde, WAIT(s): stare(Pi) blocat c(s) Pi SIGNAL(s): Pjfront(c(s)) stare(Pj) activ Observati e v(s)<=0 arata faptul ca mai sint procese in coada la semaforul s

Pentru a ilustra folosirea semafoarelor numaratoare, fie un sistem in care exista doua imprimante - deci v(s)=2. Sa consideram in continuare urmatoarea situatie:
fie

procesul Pr1 care cere o imprimanta - aceasta ii va fi alocata si v(s)<-1; in continuare, Pr2 cere si el o imprimanta, care-i va fi alocata (exista o imprimanta libera deoarece v(s) este pozitiv); la urmatoarea cerere pentru imprimanta a procesului Pr3, v(s) devine -1 si procesul este trecut in coada la semaforul pentru imprimante; cind unul dintre procesele care folosesc imprimantele o va elibera, el va executa o primitiva de tip V si deci un SIGNAL(s), care va activa primul proces din coada la semaforul s, adica Pr3. Cu ajutorul celor doua primitive (P,V) descrise mai sus se poate realiza un mecanism Producator - Consumator. Acest mecanism descrie starea unui ansamblu de doua procese in care unul produce articole de un anumit tip si celalalt le consuma. Relatia Producator - Consumator este fundamentala pentru doua procese care interactioneaza Transferul articolelor intre cele doua procese se face prin intermediul unui buffer intermediar.

Fig.23. Mecanismul Producator-Consumator Cele doua procese au, in general, viteze de functionare diferite. Situatiile limita intilnite in functionarea mecanismului sint: buffer plin, caz in care se opreste producatorul; buffer gol, situatie care conduce la oprirea consumatorului; Producatorul si consumatorul nu se pot bloca simultan.

Observatii

Pentru a modela acest mecanism se folosesc doua semafoare:

42

s1= numarul de pozitii libere din buffer-ul intermediar; s2= numarul de pozitii ocupate de articole din acelasi buffer.

Alogritmii dupa care functioneaza cele doua procese sint: PRODUCATOR repeat for ever begin *produce un articol *P(s1) *depune un articol *V(s2) end; CONSUMATOR repeat for ever begin *P(s2) *preia un articol *V(s1) *consuma un articol end;

Un caz particular de mecanism Producator - Consumator este acela in care Producatorul si Consumatorul comunica intre ele prin mesaje - aceasta situatie poate fi modelata in doua feluri: 1. In primul caz, se considera ca fiecare proces are asociat un buffer in care-si va primi mesajele. Producerea unui mesaj este descrisa de operatia SEND(m,Pr), unde m= mesajul de transmis, iar Pr= procesul receptor. Consumarea unui mesaj se face cu o primitiva de tip RECEIVE(m,Pe), unde m=mesajul primit, iar Pe= procesul emitator. Cele doua primitive arata astfel: SEND(m,Pr) daca *Pe gaseste spatiu in buffer-ul lui Pr atunci *depune mesajul in acest buffer altfel *Pe se blocheaza RECEIVE(m,Pe) daca *mesajul este disponibil in buffer-ul lui Pe atunci *Pr va prelua acest mesaj altfel *Pr se blocheaza

2. O a doua solutie de implementare a mecanismului Producator - Consumator foloseste un singur buffer comun, in/din care se depun/preiau mesaje, pe baza unei informatii de adresa. In acest caz, cele doua primitive folosite vor fi de tip SEND BY REFERENCE, RECEIVE BY REFERENCE.

43

Fig.24. Caz particular de mecanism Producator-Consumator

Modul5 Resurse. Deadlock


Termenul de "resurse" este folosit pentru a desemna entitatile fizice, respectiv logice dintr-un SC, care concura la functionarea sistemului respectiv. Ele pot fi clasificate dupa mai multe criterii, dupa cum urmeaza: 1. Resursele pot fi:

reale: UCP-ul, memoria interna, echipamentele periferice, sistemele de operare, programele utilitare etc. virtuale: memoria virtuala, echipamentele periferice virtuale;

2. Dupa tipul de acces, resursele pot fi:


cu acces unic: UCP-ul, imprimanta, unitatea de banda magnetica etc. cu acces multiplu: memoria centrala, multiplexoare, unitatea de disc, procedurile reentrante (cu cod pur) s.a.

3. Resursele se pot imparti si in:


permanente: memoria interna, UCP-ul, imprimanta, procesorul etc. temporare: mesaje, fisiere temporare (pe care un proces le produce si altul le consuma);

4. Unele resurse pot fi recuperabile (UCP-ul, memoria centrala,..), in timp ce altele nu se pot recupera (de exemplu tonner-ul de la imprimanta). 5. Exista deasemenea notiunea de resursa banalizata (echivalenta), care se refera la faptul ca exista mai multe resurse de acelasi tip, identice in ceea ce priveste functionalitatea. Ca urmare, din punctul de vedere al solicitantului, nu conteaza care sau in ce ordine i se aloca. Exemple de astfel de resurse sint: blocurile/zonele de memorie libere sau pistele unui disc. Pentru a gestiona toate aceste feluri de resurse, SO foloseste informatii referitoare la acestea cum ar fi:

unitatea de alocare, care depinde de natura resursei si de strategia de alocare ( de exemplu, pentru memoria centrala, unitatea de alocare este pagina, in timp ce pentru memoria secundara este unitatea de disc sau pista de disc; modul de reprezentare - la nivelul sistemului, fiecare unitate de alocare/resursa este descrisa de informatii cum ar fi: starea ei (libera/ocupata), beneficiarul alocarii, durata alocarii, drepturile de acces s.a.;

44

Modulele SO care asigura administrarea resurselor se numesc alocatoare. Functionarea lor se bazeaza pe folosirea cozilor de asteptare la resurse. Problema cea mai delicata, referitoare la resurse, pe care trebuie sa o rezolve un SO este blocajul reciproc (deadlock-ul). Cea mai simpla forma de deadlock consta in doua procese care asteapta, fiecare, resurse detinute de cate celalalt proces, ele nefiind constiente de aceasta. Fenomenul se poate generaliza pentru un numar oarecare de procese, care asteapta ciclic. Evident, deadlock-ul conduce la blocarea intregului SC.

Fig.25. Exemplu de blocaj reciproc Fie exemplul ilustrat de figura urmatoare: in memorie se afla doua procese A si B, care fac diverse cereri pentru resurse.
Procesul A solicita mai intii banda magnetica (magnetic type) prin cererea AC1, dupa care cere imprimanta (line printer) cu solicitarea AC2. El va face eliberarile in aceeasi ordine: mai intii banda (AE3), si apoi imprimanta (AE4). Procesul B solicita aceleasi resurse in ordine inversa (imprimanta - BC1, banda BC2), dupa care le elibereaza exact in aceeasi ordine ca si A, mai intii banda (BE3) si apoi imprimanta (BE4).

Sa ne imaginam acum urmatoarele moduri de intretesere a operatiilor de cerere/eliberare de resurse ale celor doua procese in executie: 1. AC1(MT) BC1(LP) AC2(LP) BC2(MT) - in aceasta situatie, A-ul se blocheaza in momentul solicitarii imprimantei (care este folosita de B), iar B-ul se blocheaza deasemenea cind va cere acces la banda, care este folosita de A. Ca urmare, nici-unul dintre cele doua procese nu se va putea termina niciodata; 2. AC1(MT) AC2(LP) AE3(MT) AE4(LP) BC1(LP) BC2(MT) BE3(MT) BE4(LP) - in acest caz, toate procesele se pot termina; 3. AC1(MT) AC2(LP) BC1(LP) AE3(MT) AE4(LP) BC2(MT) BE3(MT) BE4(LP) - si aceasta este o situatie fericita in care toate procesele se termina (desi B-ul se blocheaza temporar in momentul in care face prima cerere pentru imprimanta (BC1).

Fig.26. Posibile scheme de cereri de resurse Se observa ca atit in cazul al doilea, cit si in ultimul, A-ul reusise sa acapareza toate resursele necesare, inainte ca B-ul sa faca prima cerere de resursa - aceasta a fost conditia care a asigurat terminarea ambelor procese, chiar daca - in al doilea caz - B-ul a fost blocat temporar, pina la eliberarea resurselor de catre A.

45

Fenomenul blocajului reciproc a fost studiat incepind cu peste 30 de ani in urma astfel, in 1971, Hoffman enunta conditiile necesare producerii deadlock-ului pentru resurse permanente acestea sint:

excluderea mutuala in raport cu o resursa; planificarea fara prelevare fortata; alocarea partiala a resurselor (la care procesele isi obtin resursele una cite una); asteptarea circulara (in care fiecare proces isi pastreaza resursele asteptind eliberarea altora).

O data formulate aceste conditii care pot conduce la deadlock, au reiesit imediat citeva metode de prevenire a deadlock-ului:

sa nu se pretinda excludere mutuala (evident, aceasta "solutie" este nerealista pentru resurse nepartajabile, cum este imprimanta); planificarea sa se faca cu prelevare fortata (aceasta este posibil pentru memorie, pentru procesor, dar nu si pentru banda magnetica!); sa se faca alocarea totala, inca de la inceput, a tuturor resurselor; sa se elimine asteptarea circulara prin ordonarea cererilor (toate procesele sa ceara resursele in aceeasi ordine).

Inainte de a descrie citeva din tehnicile concrete de evitare a blocajului reciproc, care se bazeaza pe aceste metode, sa observam ca deadlock-ul este tratat diferit in functie de tipul SO astfel:
in sistemele in timp partajat deadlock-ul poate fi acceptat - el va fi detectat si rezolvat prelevind fortat resurse; in sistemele in timp real nu se poate accepta producerea deadlock-ului - ca urmare, ele vor implementa algoritmi de evitare a acestuia, desi ei sint complecsi si costisitori (atit ca timp, cit si ca spatiu).

Tehnici concrete de evitare a deadlock-ului 1. Prealocarea tuturor resurselor utilizate in comun Aceasta tehnica presupune ca job-ul (procesul) sa nu fie pornit de planificatorul pentru executie pina nu sint disponibile toate resursele care-i sint necesare. Citeva din neajunsurile prezentate de folosirea aceste tehnici sint: proasta utilizare a resurselor a caror alocare se face conform tabloului static al programelor, ceea ce este ineficient, precum si timpul mare de raspuns. 2. Alocarea impusa controlata In aceasta tehnica, se permite job-ului (procesului) inceperea activitatii fara alocarea tutror resurselor necesare, dar acesta este obligat totusi sa specifice cererea

46

maxima de resurse. La fiecare solicitare de resursa din partea unui job, se va executa un algoritm care decide daca, prin acceptarea acestei cereri este posibil sa se produca deadlock si, daca da, cererea se refuza (sa nu uitam insa ca este totusi sarcina SO sa garanteze timp finit de asteptare). De fapt, acest algoritm simuleaza ca r da resursa si incearca sa vada daca toate procesele existente in sistem se pot termina - daca da, atunci se va da curs cererii de resursa. acest algoritm este asemanator algoritmului bancherului, care, atunci cind i se solicita un imprumut, simuleaza ca ar da banii solicitantului si verifica daca se ajunge intr-o situatie sigura. Algoritmul folosit de alocarea impusa controlata este urmatorul:
**

algoritm testarea_posibilitatii_producerii_deadlock-ului este *sterge marcajele tuturor proceselor *considera cererea acceptata cit timp *exista un proces care se poate termina executa *marcheaza procesul ca terminat *simuleaza eliberarea tuturor resurselor sale daca *mai sint procese nemarcate atunci pericol_deadlockadevarat altfel pericol_deadlockfals

**

stop

Dezavantajele acestui algoritm sint: nu este eficient, avind o complexitate proportionala cu produsul dintre numarul de resurse si numarul de clienti; este pesimist, deoarece el indica deadlock-ul chiar si cind exista numai pericolul ca acesta sa se produca, fara a avea loc efectiv.

In plus fata de aceste dezavantaje, alocarea impusa controlata mai prezinta si urmatoarele neajunsuri:

toate cererile de resurse trebuie cunoscute apriori; rularea la fiecare cerere de resursa acestui algoritm duce la crestera overhead-ului.

3. Alocarea impusa standard (ierarhica) La folosirea acestei tehnici fiecarei resurse i se asigneaza un numar de ordine si toate cererile de resurse trebuie prezentate in ordinea crescatoare a acestui numar (de exemplu discul magnetic - 1, banda magnetica - 2, imprimanta - 3, procesorul - 4,..). Im plus fata de aceasta numerotare a resurselor, se considera ca acestea sint ierarhizate pe nivele, astfel:

47

Fig.27. Alocare ierarhica standard Acest sistem ierarhic sta sub semnul restrictiei ca toate resursele de pe un anumit nivel trebuie obtinute printr-o singura cerere (adica pentru fiecare nivel alocarea este totala). Procesul de alocare a resurselor necesare unui anumit proces se desfasoara astfel:

daca s-au obtinut toate resursele de pe nivelu Nj, in viitor se vor obtine cele de pe nivelul Nk, cu k>j, printr-o cerere asemanatoare cu cea de la Nj; eliberarea de resurse se face deasemenea total, intr-un timp finit, adica daca s-au eliberat toate resursele de pe nivelul Nj, in continuare se pot obtine cele de pe nivelul Nk, k<j.

Deadlock-ul resurselor temporare Pentru a vedea cum se pune problema deadlock-ului in sistemele Producator - Consumator pentru resurse temporare sa consideram urmatorul exemplu:

48

Fig.28. Exemplu de blocaj reciproc pentru resurse temporare Iata ca, desi producatorul si consumatorul nu se pot bloca simultan intr-un sistem simplu, intr-un sistem mai complex putem intimpina astfel de situatii nedorite. O solutie de evitare a deadlock-ului pentru resurse temporare este folosirea si in acest caz a alocarii ierarhice. Astfel, se numeroteaza corespunzator procesele (dintre care unul va fi master, iar toate celelalte slave), mesajele urmind sa se transmita din aproape in aproape, astfel:

Fig.29. Alocare ierarhica standard pentru resurse temporare Regulile de baza care se impun in functionarea acestei ierarhii sint:

sa nu se transmita un mesaj decit daca exista certitudinea ca este acceptat; sa nu se receptioneze un mesaj decit daca exista un emitator sigur pentru el; cele doua operatii de mai sus sa se faca in timp finit.

Pentru a se asigura conditia de timp finit de mai sus este necesar ca:

sa existe intelegere continua intre procesor si consumator legata de directia in/din care se transmite/receptioneaza mesajul; in interiorul proceselor toate operatiile sa se termine in timp finit; mesajele de raspuns sa fie complete astfel incit sa nu mai necesite mesaje suplimentare; daca un mesaj are nevoie de un raspuns, acesta ii va fi trimis numai daca ezxista un buffer gol, prin care sa se faca transferul.

Modul6 Sisteme multiprocesor


Practica folosirii sistemelor de calcul a demonstrat ca, daca sistemul este izolat, adica are acces la o cantitate fixa de resurse, uneori resursele sint fie nefolosite, fie insuficiente. Pentru a evita astfel de sitatii s-a ajuns la ideea punerii la un loc a mai multor sisteme de calcul, astfel incit eficienta ansamblului sa fie mai care decit eficientele sistemelor componente insumate. Un exemplu de notorietate in acest sens este cel al retelelor de calculatoare, care au aparut din necesitatea de a partaja harddisk-uri de dimensiune mare. Metodele de planificare a job-urilor (proceselor) in sistemele multiprocesor sint descrise succint mai jos: 1. Planificarea separata. Acest fel de planificare s-a aplicat pentru sisteme de tipul lui IBM360, alcatuite din 2 procesoare necuplate intre ele, fiecare cu memorie si

49

echipamente periferice prooprii. La executia unui job, un operator uman decidea inca de la inceput pe care procesor va fi rulat acesta. In plus, exista posibilitatea de a trece de la un sistme la altul atit memoria cit si echipamentele periferice; 2. Planificarea coordonata (multi-prelucrare slab conectata). Si in acest caz exista doua sisteme distincte, insa job-ul este planificat pentru executie pe un sistem sau pe celalalt de catre SO, in functie de disopnibilitatea de resurse; 3. Master-slave (multi-prelucrare puternic conectata). In acest fel de sisteme, exista un procesor master, cu memorie proprie, alaturi de un set de procesoare echivalente (si ele cu memorii locale) si de o memorie comuna in care sint incarcate procesele din lista "Pregatit pentru executie", dupa cum se poate observa si din figura urmatoare:

Fig.30. Sistem multiprocesor master-slave Observati e Pentru acest tip de sisteme, procesorul master se constituie in asa-numitul "loc ingust" (bottleneck) in sistem, in sensul ca o cadere a sa face sistemul nefunctional. Deasemenea, procesoarele slave pot sta nefolosite pentru ca procesorul master nu apuca sa le dea de lucru.

4. Planificarea omogena de procese presupune ca orice procesor din sistem poate face planificare pentru executie, in sensul ca el isi poate alege un proces din lista "Pregatit" si il poate executa. Desigur in acest caz, se pun probleme de sincronizare a accesului la aceasta lista; 5. Planificarea distribuita se intilneste in retelele de calculatoare, in care un proces poate fi rulat in orice nod liber din retea, care este disponibil. Ar mai merita facuta o singura remarca referitoare la faptul ca nici in acest caz nu dispar problemele obisnuite de gestiune a memopriei, procesorului etc. O observatie importanta referitoare la sistemele multi-procesor este aceea ca cresterea exagerata a numarului de procesoare nu conduce la cresterea performantelor, deoarece ele se vor jena intre ele incercind sa acceseze lista "Pregatit".

Modul7 - Gestiunea proceselor in Unix. Sincronizare. Comunicatie


Inainte de a vorbi efectiv despre gestiunea proceselor in Unix, sa facem citeva consideratii despre nucleul SO Unix si functiile sale de baza. Nucleul Unix este partea centrala a SO. El este alcatuit dintr-un program supervizor si un numar de rutine de control. Functia principala a nucleului este controlul efectiv al resurselor, prin gestiunea:

proceselor prin controlul executiei proceselor cu ajutorul primitivelor pentru crearea/terminarea/suspendarea/comunicarea/planificarea pentru executie in timp partajat a proceselor;

50

memoriei, adica alocarea/eliberarea memoriei centrale pentru procesele aflate in executie; fisierelor, constind in alocarea/dealocarea memoriei secundare in vederea stocarii si regasirii eficiente a informatiei, protectia fisierelor impotriva acceselor ilegale, precum si strcuturarea sistemului de fisiere intr-un mod flexibil si usor de utilizat; echipamente (dispozitive) periferice, care permite accesul controlat la dispozitivele periferice, cum ar fi imprimantele, unitatile de banda sau de disc magnetic, interfetele de retea, etc.

Structura nucleului Unix este alcatuita din urmatoarele componente:


interfata cu procesele utilizator (realizata prin intermediul apelurilor de sistem system calls); subsistemul de control al operatiilor de I/O, care are urmatoarele atributii: aloca spatiu pentru fisiere; controleaza accesul la fisiere; gestioneaza spatiul liber din memoria secundara; controleaza modul de lucru al dispozitivelor periferice, acesta putind lucra la nivel de caracter (de ex. banda magnetica), la nivel de bloc (de ex. discul magnetic) sau la nivel de bloc de lungime variabila (raw);

subsistemul de control al proceselor, cu functia de a realiza gestiunea memoriei centrale si planificarea/sincronizarea/comunicarea proceselor; interfata cu hardware-ul, care are sarcina de a trata intreruperile si de a comunica direct cu masina fizica. Acesta parte a nucleului interactioneaza cu subsistemul de I/O prin intermediul unor subrutine ed control al dispozitivelor periferice, numite driver-e. Primele trei componente ale nucleului SO Unix (care alcatuiesc 85-90% din intregul sistem) sint scrise in limbajul de programare C. Aceasta confera SO Unix un grad mare de portabilitate (independenta de masina fizica).

Observati e

Nucleul SO Unix se genereaza pornind de la surse si de la biblioteci, pe baza unei specificatii de configuratie. Initial nucleul era monolitic, adica el era incarcat in intregime in memoria interna, unde raminea rezident. Acum el este puternic modularizat, in memoria operativa incarcindu-se doar modulele necesare, pe masura ce este nevoie de ele. Procese Unix In SO Unix este fundamental conceptul de proces, adica un program in stare de executie continind urmatoarele elemente:

imaginea fisierului executabil in memorie, alcatuita din:

51

zona de cod (textul programului), care contine cod pur (reentrant), teoretic nemodificabil, protejat la scriere. Programele al caror cod este pur isi pastreaza datele in registri si variabilele contextuale pe stiva. Daca nu se poate asigura reentranta condului, acesta impreuna cu datele asociate vor fi generate in zona de date; zona de date, care este zona in care se fac alocarile statice si dinamice pentru entitatile din program. Ea este o zona a utilizatorului, in sensul ca el este responsabil pentru alocarile/dealocarile care se fac aici; zona de stiva, continind informatii legate de variabilele contextuale si de apelurile de subrutine (proceduri, functii). La nivelul sistemului, exista doua stive, una utilizator si una nucleu;

resursele utilizate in momentul executiei (registri, fisiere deschise s.a.)

52

Observatii

Imaginea in memorie a unui proces contine o eticheta din care se pot afla lungimile zonelor de cod/date/stiva, dar si informatii despre felul procesului (executabil sau nu) si starea sa. Pentru un program dat, pot exista unul sau mai multe procese active asociate (numite instante) la un moment dat. Executia proceselor utilizator se face pe doua niveluri: utilizator (in care se adreseaza numai spatiu de adrese propriu programului respectiv) sau sistem (in care se poate adresa si spatiul de adrese al nucleului). La nivelul SO exista instructiuni privilegiate, care se pot executa numai in mod nucleu.

In Unix, nucleul devine parte integranta a fiecarui proces utilizator. Mecanismul de trecere intre cele doua moduri de lucru este urmatorul:

Fig.31. Trecerea intre modurile de lucru posibile In decursul existentei sale, un proces se poate afla intr-una din starile:

creat, aflat intr-o faza de pornire; gata de rulare (procesele aflate in aceasta stare sint ordonate intr-o coada, dupa prioritati); in executie in mod utilizator; in executie in mod nucleu; in asteptare, pe disc (swapped) sau in memorie; zombie, adica starea in care se afla un proces care in momentul terminarii sale a transmis deja semnalul de terminare parintelui sau. Acesta urmeaza sa elibereze intrarea corespunzatoare procesului terminat din tabele de procese de la nivelul SO;

O intrare in tabela de procese a SO arata astfel:

Fig.32. O intrare in tabela de procese a SO In SO Unix procesele se genereaza arborescent, astfel:

Fig.33. Arborele de procese in UNIX Observati e

Sistemul trateaza uniform atit comenzile, cit si procesele utilizator. Chiar si interpretorul de comenzi (SHell) este lansat in executie ca orice alt program;

53

In sistem exista mai multe Shell-uri, dintre care se poate alege unul la un moment dat. Un apel al interpretorului de comenzi da nastere unui proces, care se adauga celorlalte existente in sistem. El este pus in executie imediat dupa lansarea comenzii.

Gestiunea proceselor in Unix In Unix, gestiunea proceselor este realizata de catre planificatorul pentru executie (Scheduler) si este in timp partajat. Prioritatile sint diferentiate dupa modul de lucru (utilizator/sistem) si sint recalculate dinamic, functie de timpul de executie consumat de catre procesul respectiv. Controlul timpului de lucru al proceselor este asigurat de actre un driver de ceas. In continuare vor fi prezentate citeva consideratii referitoare la principalele operatii legate de procese, in SO Unix: 1. Crearea unui proces (fiu) este realizata de catre un alt proces (parinte). Ea consta in crearea unui proces fiu al procesului parinte, care are identificator si descriptori de sine statatori si, initial o imagine identica cu a parintelui sau. Directiva de creare a proceselor este fork(), avind prototipul int fork(); si are loc conform figurii de mai jos:

Fig.34. Crearea unui proces Controlul este dat procesului fiu exact in locul in care se afla in executie parintele sau. De obicei, parintele asteapta terminarea executiei fiului sau intrind intr-o stare de adormire, din care se trezeste cind fiul isi termina executia. Operatiile efectuate de nucleu pentru a realiza un fork() sint:
alocarea

unei intrari noi in tabela de procese, in care se vor memora informatiile caracterizind procesul nou creat; atribuirea unui identificator (PID - Process IDentifier) unic pentru procesul fiu; realizarea unei copii logice a imaginii din memorie corespunzatoare parintelui sau; incrementarea numarului de referinte pentru fisierele asociate procesului parinte; transferarea procesului fiu, in functie de memoria disponibila, fie in starea gata de rulare in memorie, fie in starea gata de rulare, pe disc (swapped); Directiva fork() intoarce PID-ul procesului fiu in procesul parinte si valoarea 0 in procesul fiu. Procesul fiu poate executa in continuare:

54

acelasi cod cu procesul parinte: int p; p=fork(); <cod executat in ambele procese>

cod diferit de cel al procesului parinte: int p; if ((p=fork()==0) <cod executat doar in fiu> else <cod executat doar in tata>

2. Punerea in executie a unei noi imagini are ca efect inlocuirea imaginii procesului care se executa, cu una transferata dintr-un fisier. Controlul este dat punctului de start din noua imagine. Directiva cu care se executa aceasta operatie este exec(..). Prototipul acestei directive este:
exec(numele_fisierului_executabil, parametri_din_linia_de_comanda_pentru_fisierul_executabil).

Ea este folosita ca in figura urmatoare: Fig.35. Lansarea in executie a unei noi imagini Schema generala de folosire a celor doua directive este un fork(), urmat de un apel al lui exec in procesul fiu. Un exemplu de aplicare a acestei scheme are loc atunci cind Shell-ul (parinte) primeste o comanda (fiu). El va da nastere unui proces fiu (fork), care va lansa in executie imaginea corespunzatoare comenzii aflate undeva pe harddisk (exec). Trebuie remarcat ca la apelul directivei exec nu se creeaza un proces nou, ci se fac doar unele modificari in zona utilizator din intrarea in tabela de procese. 3. Distrugerea proceselor se face prin transmiterea catre procesul vizat a unui semnal SIGTERM. Un proces va testa acest semnal la inceputul fiecarei cuante de executie deltat. Acest semnal poate fi ignorat, tratat printr-o actiune standard sau tratat printr-o rutina a procesului. Este de remarcat ca, prin modul de tratare al semnalului de terminare, Unix-ul da posibilitatea controlului duratei de viata a proceselor din sistem proceselor utilizator. Sincronizarea proceselor Sincronizarea proceselor poate sa fie controlata de catre sistem (printr-un mecanism de tip pipe) sau de catre utilizator (prin semnale emise la producerea unor evenimente). Un eveniment este o modalitate de precizare a nomentului in care un proces blocat trece in starea gata de rulare. Sincronizarea prin semnale se implementeaza cu ajutorul unor biti memorati in tabela de procese. Ei pot fi setati de catre utilizator sau de catre nucleu, la producerea

55

unor evenimente hardware. Nucleul verifica primirea unui semnal (setarea bitului corespunzator acestuia) la trecerea din mod sistem in mod utilizator si inainte/dupa blocarea unui proces. Standard-ul Unix System V recunoaste 19 semnale dinter care se pot aminti: terminare proces, diverse erori etc. Actiunea asociata implicit primirii unui semnal este terminarea procesului, dar exista si posibilitatea folosirii semnalelor pentru a declansa actiuni specifice, folosind functia signal(numar_semnal, adresa_rutinei_de_tratare_semnal). Trebuie insa remarcat ca nu toate semnalele pot fi tratate in mod utilizator. Sincronizarea unui proces tata cu fii sai se face cu ajutorul directivei wait, care blocheaza procesul tata pina la terminarea unui dintre fii sai sau pina la primirea unui semnal. Sincronizarea intre procese oarecare se face prin intermediul urmatoarelor directive de sistem:

kill(PID,numar_semnal) - transmite un semnal de terminare unui proces; pause() - blocheaza procesul curent pina la primirea unui semnal; alarm(sec) - trimite un anumit semnal dupa un interval de timp (in secunde); Tot pentru sincronizare se poate folosi si functia de biblioteca urmatoare: sleep(sec) - suspenda executia procesului curent pentru timpul "sec", dupa care-l deblocheaza; sleep(eveniment_asteptat) - suspenda procesul curent in executie pina la producerea evenimentului dat ca argument.

Comunicarea intre procese Comunicare intre procesele Unix se poate face prin:

fisiere obisnuite - acest mod de comunicare este cel mai simplu si cel mai direct, dar este ineficient - in general - pentru ca nu ofera controlul automat al accesului concurennt, lasindu-l partial in sarcina programatorului; fisiere de tip pipe - acestea sint fisiere obisnuite in care operatiile de R/W se ealizeaza FIFO (First In First Out). In acest caz accesul este controlat automat de catre SO. Fisierele pipe pot fi: anonime: acestea pot fi folosite numai intre tata si fii sai, sau intre frati (deoarece fisierul pipe este identificat doar de descriptorii sai aflati in zona utilizator, care sint mosteniti doar de fii procesului tata. Un exemplu de folosire a pipe-urilor anonime este urmatorul: int p[2]; pipe(p); /* p[0]= descriptor pentru citire */ /* p[1]= descriptor pentru scriere */ write(p[1], adresa, numar_inregistrari); read(p[0], adresa, numar_inregistrari); cu nume: ele se creeaza in cadrul unui director, ca un fisier obisnuit, eliminind astfel limitarile pipe-urilor anonime;

56

cozi de mesaje - acest mecanism este cel mai puternic din pachetul IPC (InterProcess Communication), din care mai fac parte si celelate doua modalitati de comunicare, prezentate in continuare. El este implementat cu ajutorul unei cozi de mesaje gestionate in intregime de catre SO. Aceasta coada este practic buffer-ul intermediar dintr-un mecanism Producator - Consumator. Astfel procesele care cer mesaje se blocheaza pina cind gasesc in aceasta coada mesajele dorite, iar cele care transmit mesaje se blocheaza daac coada este plina si nici-un proces nu receptioneaza. Primitivele folosite pentru a realiza acest mecanism sint: msgget (creeaza structurile de date folosite), msgop (realizeaza operatiile specifice de comunicare) si msgctl (controleaza structurile de date folosite, prin operatii de actualizare, afisare a valorilor continute etc.); zone de memorie partajata - in acest caz, mai multe procese utilizeaza in comun o aceeasi zona de memorie, prin map-area in acest spatiu a unei zone din spatiul lor virtual. Accesul este controlat in totalitate de catre utilizator. primitivele folosite sint: shmget, shmop si shmctl. Ele au functionalitati similare celor de mai sus; semafoare - acesta este mecansimul clasic de lucru cu semafoare, extins cu posibilitatea de a actiona mai multe semafoare apartinind unei multimi, la un singur apel de functie. Primitivele utilizate sint similare celor prezentate anterior si au denumirile: semgett, semop si semctl.

57

Sumar

Capitolul de gestiune a proceselor/procesoarelor abordeaza probleme legate de planificarea de job-uri, planificarea de procese, interactiunea si sincronizarea proceselor, mecanismul Producator-Consumator, precum si problema deadlock-ului pentru resurse permanente/temporare. In final, sint punctate elementele esentiale reeferitoare la administrarea proceselor in Unix. 1. 2. Care dintre planificarile pentru executie (job-uri/procese) are prioritate mai mare? Faceti o paralela intre mono- si multi-programare din punctul de vedere al eficientei lor. 3. Care dintre politicile round-robin este cea mai avantajoasa din punctul de vedere al unui proces dat? Dar din punctul de vedere al SO? 4. In ce situatii se poate produce deadlock intr-un SO? 5. Pe ce se bazeaza afirmatia ca imbatrinirea creste prioritatea proceselor? 6. Comparatoe intre planificarea master-slave si planificarea omogena in sistemele multi-procesor. 7. Exemple de folosire a mecanismului producator consumator. 8. Un SO poate sa functioneze corect fara sa impuna excludere mutuala in raport cu vreo resursa? 9. Care este legatura intre notiunile de time-sharing si prelevare fortata?

Exercitii Subiecte pentru dezbatere

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