Sunteți pe pagina 1din 118

Aritoni Ovidiu

Sisteme de operare 1

1.Introducere

Aritoni Ovidiu

Sisteme de operare 1

Fr software-ul su, un computer este n mod sigur o cutie de metal. Cu ajutorul software-ului computerul poate stoca, procesa, i recupera informaii, poate afia documente multimedia, poate cuta pe Internet, i se poate angaja n multe activitii. Softul unui calculator poate fi mprit n 2 categorii: programe-sistem, care administreaz sistemul nsi; aplicaii-program, care realizeaz o sarcin cerut de utilizator. Programele sistem fundamentale sunt sistemele de operare, care controleaz toate resursele calculatorului i ofer o baz peste care o aplicaie-program poate scrie. Un sistem modern conine unul sau mai multe procesoare, ceva memorie (RAM, ROM, etc.), discuri, imprimante, plac de reea, i alte echipamente de intrareieire. Este o treab dificil de a urmri ca toate componentele s ruleze corect i optim. Dac fiecare program s-ar interesa asupra cum i lucreaz hard diskul sau ce multe alte lucruri se pot ntmpla cnd este citit un bloc de disc, este puin probabil ca acel program s mai ruleze. Cu muli ani n urm a devenit extrem de clar c trebuie gsit un scut pentru complexitatea hardware-ului unui calculator. Aceast idee a evoluat gradat i a impus, practic vorbind, un strat la baza componentei hardware care s administreze toate componentele unui sistem i s prezinte utilizatorului o interfa sau o main virtual uor de neles i de programat. Acest strat de software este sistemul de operare i formeaz subiectul lucrrii. Situaia aceasta este prezentat mai jos:

Fig 1-1. Un sistem de calcul consta in hardware, programe de sistem si aplicatii La baz este hardware-ul, care n multe cazuri este compus din 2 sau mai multe nivele. Cel mai de jos nivel conine echipamente fizice, constituite din circuite integrate, chipuri, cabluri, surse de putere, tuburi catodice i alte echipamente fizice similare. Cum sunt construite i lucreaz acestea, sunt sarcini ce cad asupra inginerilor. Dup acest nivel pe unele sisteme urmeaz un altul al software - ului primitiv care controleaz direct aceste echipamente i ofer o interfa mai simpl pentru urmtorul nivel. Acest software, numit microprogram, este n mod obinuit gsit n memoria ROM. El este astzi un interpretor, ce aduce un limbaj de instruciuni de genul ADD, MOVE sau JUMP care rezult ca serii de mici pai. Pentru a aduce o instruciune ADD de exemplu, microprogramul trebuie s determine unde numerele ce trebuie adugate sunt localizate, s se deplaseze, i s le adauge i s depoziteze rezultatele undeva. Setul de intruciuni pe care microprogramul l interpreteaz definete limbajul main, care nu este 2

Aritoni Ovidiu

Sisteme de operare 1

deloc parte a hardwareului, ci productorii de computere l descriu n manualele lor n aa fel nct muli oameni l consider a fi adevrata main. Unele computere numite RISC, nu au un nivel de microprogramare. Pe aceste maini hardul execut direct instruciunile n limbajul de asamblare. Ca de exemplu Motorola 680 x O are un nivel de program dar IBM power PC nu are. Limbajul de asamblare are ntre 350 500 de instruciuni, cele mai multe pentru mutarea datelor, pentru calcule aritmetice i pentru a compara valori. Pe acest nivel (strat) dispozitivele de intrare i ieire sunt controlate de valorile ncrcate n registre speciale. De exemplu un disk poate fi programat s citeasc ncrcnd valorile adreselor discului, adresa principal a memoriei, byte count-ul i direcia (citete sau scrie) n registrele speciale. n practic este nevoie de mult mai muli parametrii i datele rezultatelor dintr-o operaie sunt foarte complexe. Mai departe pentru multe dispozitive de intrare/ieire timpul joac un rol important n programare. O funcie major a SO este de a ascunde toat aceast complexitate i de a da programatorului un set mai convenabil de instruciuni cu care s lucreze. De exemplu blocul de citire dintr-un fiier conceptual este mai simplu dect de a te ngrijora despre detaliile mutrii capetelor discului, ateptnd ca ele s se stabilizeze .a. m.d. Vrful sistemului de operare este restul software-ului. Aici gsim interpretorul de comenzi (shell), sistemele de ferestre, compilatoarele, editoarele i programele de aplicaie. Este important s ne dm seama c aceste programe cu siguran nu fac parte din sistemul de operare, chiar dac n mod caracteristic sunt aprovizionate de productorii de computere. Aceasta este un punct foarte important i subtil. Sistemul de operare este acea parte a softului care ruleaz n modul Kernel sau n modul supervizor. Sistemul de operare protejeaz asupra atingerilor (abuzurilor) utilizatorului asupra hardwarelui (ignornd pentru un moment nite microprocesoare care nu au deloc protecie). Compilatoarele i editoarele lucreaz n modul user. Dac unui utilizator nu i place un anumit compilator el este liber s scrie propriul compilator dac dorete aceasta. Nu este ns liber s scrie propriul su program de ntrerupere a funcionrii diskului care este parte a sistemului de operare i n mod normal este protejat de hardwarelui mpotriva atacurilor utilizatorilor ce vor s l modifice. Mai presus de programele sitemului sunt programele de aplicaie. Aceste programe sunt cumprate sau scrise de utilizator pentru a le rezolva problemele personale, ca de exemplu, procesarea textelor, imprimare, calcule sau jocuri.

1.Ce este un Sistem de Operare?


Muli ulitizatori de computere au avut experiene cu un sistem de operare dar este dificl de a spune cu exacticitate ce este un sistem de operare. O parte a problemei este c sistemele de operare desfoar dou funcii de baz care nu au legtur una cu alta. i depinznd de cine vorbete ai auzit mai mult de o funcie sau cealat. Haidei acum s ne uitm la amndou.

Aritoni Ovidiu

Sisteme de operare 1

A.Sistemul de operare ca i main extins


Aa cum este menionat mai sus, arhitectura (setul de intruciuni, organizarea memoriei, dispozitivele de I/O, structura de baz) multor calculatoare la nivelul limabajului main este primitiv i ciudat pentru program n special pentru I/O. Ca s clarificm mai mult acest punct haidei s ne uitm pe scurt la cum este fcut o dischet folosind NEC PD765 sau echivalentul care este folosit pe majoritatea PC-urilor (de-a lungul ntregii crii vom folosi termeni de floppy disc sau dischet fr nici o diferen) PD765 are 16 comenzi fiecare ncrcnd ntre 1-9 bytes ntr-un registru. Aceste comenzi sunt pentru citirea i scrierea, mutarea capului de disc i formatarea datelor, ca i pentru iniializarea, nregistrarea/detectarea, resetarea i recalibrarea controlerului i a driverului. Cele mai importante comenzi de baz sunt cele de citire i scriere, dintre care fiecare cere 13 parametrii mpachetai n 9 bii. Aceti parametrii specific elemente ca de exemplu, adresa blocului ce urmeaz a fi citit, numrul sectoarelor pe disc, modul de nregistrare folosit pe mediul fizic spaierea discului i ce s faci cu adresa datelor terse. Dac nu nelegi acest mecanism nu te ngrijora, asta este de fapt ideea, este mai degrab ezoteric. Cnd operaia este completat controlerul returneaz 23 de rezultate i corpuri de erori mpachetate n 7 bytes. Ca i cnd nu ar fi suficient programul dischetei trebuie s fie tot timpul contient dac motorul este nchis sau deschis. Dac motorul este nchis trebuie s fie deschis cu o mare ntrziere de pornire nainte ca datele s poat fi citite sau scrise. Motorul nu poate fi lsat pornit mai mult timp cci discheta se va uza. Astfel utilizatorul este forat s trateze schimbul dintre ntrzierea lung a pornirii i uzarea dischetelor (i pierderea datelor de pe ele). Fr a intra n detaliile adevrate trebuie s fie clar c programatorul obinui probabil nu vrea s se implice prea repede n programarea dischetelor (sau a hard diskului care sunt la fel de complexe i destul de diferite). n schimb ceea ce programatorul vrea este s trateze o simpl abstracie la nivel nalt. n cazul discurilor o abstracie tipic ar fi aceea c discul conine o colecie de fiiere definite. Fiecare fiier poate fi deschis pentru citire sau scriere, nchis sau deschis i n cele din urm nchis. Detalii ca de exemplu dac nregistrarea trebuie sau nu s foloseasc modificarea frecvenei i care este starea motorului la momentul acela, nu trebuie s apar n abstracia prezentat utilizatorului. Programul care ascunde de programator adevrul despre hardware i prezint o imagine drgu i simpl a fiierelor definite care pot fi citite sau scrise, desigur este sistemul de operare. Aa cum sistemul de operare scutete programatorul de aspectele hardware i prezint o simpl interfa orientat pe fiier, la fel provoac o mulime de lucruri neplcute n ceea ce privete ntreruperile, timpul i administrarea memoriei i alte trsturi de nivel sczut. n fiecare caz abstracia oferit de sistemul de operare este mai simplu i mai uor de folosit dect hardware-ul. Din acest fapt punct de vedere funcia sistemului de operare este de a prezenta utilizatorului un echivalent al mainii extinse sau mainii virtuale, cci este mai uor s programezi dect s administrezi hardware-ul. Cum i obine sistemul de operare elul este o poveste lung pe care o vom studia detaliat de-a lungul acestei cri.

Aritoni Ovidiu

Sisteme de operare 1

B.Sistemul de operare ca i manager de resurse


Conceptul de sistemul de operare care n primul asigur utilizatorului o interfa convenabil este o viziune de sus n jos. O alternativ de vedere de sus n jos susine c sistemul de operare este acolo pentru a administrara toate piesele unui sistem complex. Computerele moderne conin procesoare, memorii, ceasuri interne, dicuri, mouse-uri, plci de reea, imprimante, i o larg varietate de alte dispozitive. n vedere alternativ funcia sistemului de operare este de a furniza memorie, dispozitive de I/O, pentru repartizarea ordonat i controlat a procesoarelor. Imaginai-v ce s-ar ntmpla dac trei programe ce ruleaz pe computer, toate ncercnd s tipreasc n acelai timp rezultatul lor pe aceeai imprimant. Primele linii ale tipririi ar putea forma programul, urmtoarele programe 2, alte cteva programul 3, .a.m.d. Rezultatul lor ar fi un haos. So poate aduce ordine n potenialul haos bufferiznd toate rezultatele destinate pentru tiprirea pe disc. Cnd un program este terminat sistemul de operare poate apoi s copieze rezultatele programului de pe bufferul din disc unde a fost stocat n timp ce n acelai timp alt program poate continu s genereze rezulate ,in ciuda faptului c rezultatul nc nu merge la imprimant. Cnd un calculator (sau o reea) are mai muli utilizatori, nevoia de administrare i protejare a memoriei, a dispozitivelor de I/O i a altor resurse este mai mare, din moment ce utilizatorii ar putea s se interfereze unii cu alii. n plus, deseori utilizatorii trebuie s mpart nu numai hardul ci de asemenea i informaii (fiiere, BD). Pe scurt aceast imagine a sistemului de operare susine c principala lui datorie este s contabilizeze cine, ce resurse folosete, s aprobe cereri de resurse, i s medieze confilcte ntre cereri de la diferite programe i utilitare.

2.Generatii de calculatoare
n ziua alegerilor din 1952, maina UNIVAC de la Remington Rand a fost prezentat la televiziunea naional. Dwight D. Eisenhower i Adlai Stevenson candidau la preedinia Statelor Unite i, pe msura primirii rezultatelor de pe coasta de est, salariaii firmei Remington Rand le introduceau n UNIVAC, care era programat s anticipeze ctigtorul pe baza rezultatelor pariale. Reeaua de televiziune CBS trebuia s anune ctigtorul stabilit de UNIVAC la ora nou, dar la timpul stabilit, comentatorii CBS au anunat c UNIVAC nu a dat nici un rezultat. De fapt, UNIVAC stabilise deja un rezultat: calculele sale l indicau pe Eisenhower ca fiind ctigtor n mod detaat. Comentatorii refuzaser s anune predicia deoarece (ca i toi locuitorii rii) crezuser c ntre cei doi candidai va fi o competiie strns. Mai trziu n aceeai sear, cnd a devenit clar c UNivac anticipase corect rezultatele, CBS a anunat rezultatul preliminar i UNIVAC a ctigat imediat credibilitate din partea publicului american. Capacitile televizate ale sistemului UNIVAC au permis marii majoriti a americanilor neimplicai n tiina calculatoarelor s priveasc sistemele de calcul ntr-un 5

Aritoni Ovidiu

Sisteme de operare 1

mod nou i au contribuit la intrarea in era calculatoarelor comerciale. ncepnd cu UNIVAC i alte programe similare, dezvoltarea calculatoarelor comerciale a cuprins patru etape distincte, numite generaii de calculatoare. Astzi, ne aflm la grania celei de-a cincea generaii. Prima generaie: Tuburi cu vid (1942-1956)

Calculatoarele electronice din prima generaie, cum a fost UNIVAC, prelucrau datele utiliznd tehnologiile tuburilor cu vid experimentate pentru sistemele ABC, ENIAC i EDVAC. Aceste calculatoare erau numite sisteme mainframe (cadru principal) datorit cadrelor de metal utilizate pentru susinerea tuburilor cu vid. Tuburile cu vid sunt asemntoare unor becuri electrice de dimensiuni mari, care necesit un timp oarecare pentru a se nclzi i rspndesc cantiti uluitoare de cldur. Miile de tuburi cu vid din calculatoarele de genul ENIAC trebuiau toate nclzite i, la terminarea lucrului, era necesar o verificare amnunit pentru a nlocui eventualele tuburi arse. Tuburile cu vid sunt att de mari nct, dac s-ar utiliza i astzi n construcia calculatoarelor, un sistem mainframe modern ar avea dimensiunile unui zgrie-nori. Calculatoarele din prima generaie conineau tamburi magnetici pentru stocarea datelor. Programele stocate erau scrise n limba main, secvene de cifre 0 i 1 care reflectau direct contribuia lui George Boole. Fiecare productor crea propriul su limbaj de main. Grace Hopper, care a lucrat cu Hoeard Aiken la caculatorul Mark n anii 1940, a nceput s colaboreze cu Mauchly i Eckert dup acetia prsiser coala Moore. Hooper a realizat n 1952 primul compilator un program care traduce un limbaj de programare n limbaj main. Compilatoarele au schimbat modul de programare, permind programatorilor s introduc numere i litere n locul unor secvene de 0 i 1. De asemenea, astfel a crescut semnificativ numrul persoanelor dornice s se familiarizeze cu programarea calculatoarelor. A doua generaie: Tranzistoare (1956-1963)

n 1948, trei fizicieni ai laboratoarelor Bell- William Shocklez, Walter Brattain i John Bardeen au descoperit un nou tip de cristal numit germaniu. Germaniul nu era un conductor de electricitate att de bun cum sunt cuprul sau oelul, dar era mai bun dect alte materiale cum ar fi sticla sau cauciucul. Acest tip de material a fost denumit semiconductor. A urmat descoperirea altor materiale semiconductoare, inclusiv siliciul, care erau confecionate din materii brute uor de procurat - pietre sau nisip. Fizicienii au decoperit c, prin adugarea altor materiale la un semiconductor (proces denumit dopare), rezulta un material capabil s acioneze ca un redresor sau un amplificator electric cu alte cuvinte, un material ce putea s nlocuiasc tuburile cu vid . Aceste noi dispozitive create pe baza materialelor semiconductoare au primit numele de tranzistoare. Tranzistoarele erau de dimensiuni mult mai mici (a cinzecea parte din dimensiunea uni tub cu vid), furnizau mai mult energie i erau mai solide dect fragilele tuburi cu vid produse din sticl. In 1953 a fost lansat primul dispozitiv prevzut cu 6

Aritoni Ovidiu

Sisteme de operare 1

tranzistoare destinat vnzrii: un sistem de mbuntire a auzului care ncpea n pavilionul urechii. Ctre sfritul deceniului, tranzistoarele au nlocuit tuburile cu vid n calculatoare, televizoare i aparate de radio cu tranzistoare primele aparate de radio sufucient de mici pentru a putea fi transportate ntr-un buzunar. Aplicaiile care utilizau tranzistoarele erau numite n stare solid, nct tranzistoarele erau rezistente. Noua tehnologie n stare solid a fost utilizat pentru construirea primelor supercalculatoare , calculatoare uriae destinate gestionrii unor cantiti mari de date i efecturii unor calcule rapide. n anii 60, calculatoarele main frame din a doua generaie erau fabricate de companii cum ar fi IBM, Honeywell i Sperry-Rand (n prezent component a Unisys) i erau utilizate pe scar larg n afaceri importante. n 1957, Grace Hopper a creat un limbaj de programare destinat afacerilor denumit Flow-Matic. n 1960, Hopper a contribuit la dezvoltarea limbajului COBOL (Common Business-Oriented Language Limbaj obinuit orientat pe afaceri). Bazat pe Flow-Matic, COBOL era primul limbaj de nivel nalt care nu era specific unui anumit tip de main. (Limbajele de programare de nivel nalt seamn cu limba englez, spre deosebire de secvenele de 0 i 1 ale limbajului main.) Programele scrise n COBOL erau apoi traduse n limbaj main utiliznd un compilator de COBOL. Pn n anii 80, majoritatea programelor comerciale au fost scrise n COBOL; programele tinifice erau scrise n FORTRAN (Formula Translator). n cea de-a doua generaie de calculatoare, mbinarea ntre limbajele de programare de nivel nalt cum ar fi COBOL i FORTRAN i conceptul de program stocat inventat de von Neumann a dus la crearea unor sisteme de calcul de uz general, cu adevrat flexibile. Un program putea fi ncrcat rapid n memoria calculatorului (construit cu tranzistoare i nu cu tuburi), putea fi rulat i apoi nlocuit cu un alt program. Datorit crerii noilor limbaje de programare i construirii unui numr mare de calculatoare, au aprut noi ocupaii: programator i analist de sistem. n 1957, IBM a lansat prima unitate de disc capabil s efectueze att operaii de citire, ct i de scriere pe un disc. n 1959, Digital Equipment Corporation (DEC) a creat minicalculatorul PDP-1. De dimensiuni mai reduse dect sistemele mainframe, minicalculatoarele erau prezentate pe pia ca sisteme compacte puternice. n plus, erau ieftine: calculatorul PDP-8 costa mai puin de 100.000 de dolari. La sfritul anilor 50 a avut loc o alt premier: eliberarea cecurilor realizat de calculatoare i nu de mn. Lucrtorii de la Banca Americii, cea mai mare banc din lume, aveau probleme legate de durata foarte mare a introducerii informaiilor din cecuri n conturile bancare. Aadar, n 1959, societatea General Electric a instalat noua metod de nregistrare electronic a informaiilor de contabilitate (Electronic Recording Method of Accounting ERMA) la Banca Americii. Erma utiliza Calculatoare pentru nregistrarea cecurilor numerotate cu cerneal magnetic i era capabil s sorteze i s nregistreze de dou ori mai multe cecuri pe minut dect un contabil pe or. A doua generaie a inclus i primul patent penru un dispozitiv de tip robot, acordat lui George Devol Jr. i Joseph Engelberger n 1954. n 1958, Devol i Engelberger au instalat primul robot industrial, UNIMATE, ntr-o uzin de asamblare General Motors. n acelai an, Chester Carolson a creat prima main de fotocopiere: xerocopiatorul. A treia generaie: circuite integrate (1964-1971)

La nceputul celei de-a treia generaii de calculatoare, tranzistoarele erau deja utilizate de aproximativ 12 ani, devenind mai compacte i mai fiabile pe msura 7

Aritoni Ovidiu

Sisteme de operare 1

perfecionrii procesului de fabricaie. Spre sfitul anilor 50, tranzistoarele ajunseser de dimensiuni att de mici nct a aprut ideea combinrii mai multor tranzistoare ntr-un singur dipozitiv. n anul 1958, un inginer pe nume Jack Kilby a proiectat circuitul integrat cu cuar. Primul circuit integrat coninea trei componente ntr-un singur modul confecionat. Un grup de ingineri de la compania Fairchild Semiconductor (prima companie din Silicon Valley, California) ncerca, de asemenea, s pun n practic ideea integrrii mai multor tranzistoare i circuite ntr-un singur cip. Inginerul Jack Hoerni a descoperit un mod de a fabrica tranzistoare plate, care au permis construirea unor module de circuite integrate plate cipuri pentru calculatoare. Perfecionarea continu a tehnologiei a determinat includerea unui numr mai mare de componente ntr-un cip. Dimensiunile calculatoarelor erau n scdere, dar preul cipurilor era nc mai mare dect preul componentelor individuale. Trecerea de la o generaie la alta nu are loc peste noapte. Cnd a fost invetat tranzistorul, existau nc stocuri ntregi de tubuir cu vid care ateptau s fie utilizate. Multe calculatoare din generaia a doua conineau att tubuir cu vid, ct i tranzistoare iar tranzistoarele au fost folosite mpreun cu circuite integrate la construirea calculatoarelor din a treia generaie. Cursa trimiterii unui om pe lun a avut o contribuie important la scderea preurilor cipurilor. Uniunea Sovietic a lansat primul satelit, Sputnik n 1957. n 1961, preedintele SUA John F. Kennedy, cutnd o cale de a ctiga ncrederea naional, a promis c Statele Unite vor trimte un om pe lun pn la sfritul deceniului. Nu preul unei asemenea aventuri a fost o mare problem, ci dimensiunea vehiculului. Pentru a computeriza vehiculele spaiale, era necesare construirea unor circuite integrate mai compacte de ctre companii cum a fost Fairchild. n schimb, sprijinul acordat de guvern cercetrii i producerii de circuite integrate a permis construirea unor numr mai mare de cipuri complexe la un pre sczut. Un alt progres major al celei de-a treia generaii a fost crearea sistemelor de operare. Sistemele de operare sunt programe care controleaz instruciunile de baz ale unui calculator, inclusiv deplasarea instruciunilor i datelor ntre unitatea de prelucrare i memorie, tiprirea i citirea informaiilor de pe disc . naintea apariiei sistemului de operare, de exemplu, fiecare program conine numeroase linii de cod ce specificau exact modul de deschidere a unui fiier. Utiliznd un sistem de operare, este suficient ca programul s conin codul necesar pentru a trimite cererea de deschidere a fiierului ctre sistemul de operare care efectuau un apel de sistem. Acesta trateaz operaia de deschidere a fiierului. Sistemele de operare standardizate permit scrierea unor programe de dimensiuni mai reduse i ntr-un ritm mai rapid. Cu toate progresele nregistrate de tehnologia sistemelor de calcul, pn la calculatoarele personale moderne mai era nc un drum lung de strbtut. n schimb, time-sharing a fost expresia magic a anilor 60. Datorit tehnicii time-sharing utilizatorii nu mai trebuia s stea la coad care s lucreze la un calculator; calculatorul trecea de la un utilizator la altul, acordndu-i fiecruia cte un scurt interval de timp. ntruct calculatoarele lucreaz mai rapid dect oamenii, utlizatorii putea lucra ntr-un ritm constant i nu observau c sistemul lucrase cu altcineva n ultima zecime de secund. Imaginea predominant asupra viitorului era urmtoarea: o serie de calculatoare de dimensiuni enorme, capabile s deserveasc fiecare mii de utilizatori n sistemul time-sharing, utilizatori care introduceau pe cartele perforate i primeau datele de ieire la o imprimant. Inginerul Douglas Engelbart de la Institutul de Cercetri Standorf a avut o alt idee: calculatoare indiviuale care furnizeaz datele de ieire prin intermediul unor 8

Aritoni Ovidiu

Sisteme de operare 1

dispozitive cu tuburi catodice similare televizoarelor (nu la imprimant) i permit utilizatorilor s manipuleze imagini i s introduc texte. La sfritul anului 1968, Engelbart i-a susinut proiectul la o conferin despre calculatoare, prezentnd schema unui calculator care coninea o tastatur i un dispozitiv de indicare denumit mouse. n 1970, Engelbart a proiectat interfee cu utlizatorul prevzute cu multe ferestre, predecesoarele sistemului Windows, i a implementat un sistem de pot electronic bazat pe un sistem mainframe. Engelbart spera ca imaginea sa asupra calculatoarelor personale s schimbe radical direcia n care se ndreptau comapanii cum ar fi IBM, Sperry i DEC dar marile companii nu credeau nc n existena unei piee de desfacere pentru calculatoarele uor de utlizat, orientate pe imagini. A patra generaie: Circuite microminiaturizate (1971-?)

La nceputul anilor 70, dimensiunile circuitelor continuau s scad. Utilizarea integrrii pe scar larg (LSI large scale integration) a permis productorilor s includ sute de componente ntr-un singur cip. Tehnica LSI a fost nlocuit cu VLSI (integrate pe scar foarte larg very large scale integration), ceea ce permitea includerea a sute de mii de componente ntr-un cip. Prin utilizarea USI (integrrii pe scar utra larg), numrul componentelor dintr-un cip a ajuns de ordinul milioanelor. n 1971, o companie mic numit Intel (n prezent cel mai mare productor de cipuri din lume) a instalat toatele componentele eseniale ale unui calculator ntr-un singur cip: microprocesorul. Microprocesoarele erau produse de sine stttoare un microprocesor poate fi introdus n orice calculator sau orice alt dispozitiv. Calculatoarele au scpat de carcasele de metal, gsindu-i locul n automobile, cuptoare cu microunde i sisteme stereo. n plus, microprocesoarele erau ieftine n comparaie cu procesoarele utilizate n sistemele mainframe i n minicalculatoare. La nceputul anilor 70, Atari a utilizat un microprocesor pentru crearea primului joc video, Pong, n care doi juctori roteau manete ce controleau micarea paletelor ntrun miniaturizat de tenis de mas. Centipede i MIssile Command; la nceputul anilor 80, entuziatii jocurilor se puteau amuza cu jocuri de acest gen la ei acas. N-a durat mult pn cnd productorii de jocuri mecanice ca Wiliams, Bally i Data East au introdus microprocesoare n mesele de jocuri mecanice pentru a controla sumele ctigate pentru afiarea scorurilor. Crearea unui microprocesor a transformat n realitate viziunea lui Engelbart privind calculatoarele personale. Primul micoprocesor comercial a devenit disponibil n 1971. Anul urmtor, pe pia a existat un microcalculator, dei primul calculator personal comercial de succes Apple II a fost produs abia n 1976. n 1992, erau utilizate 65 de milioane de calculatoare. Restul, dup cum se spune, este istorie . O dat cu inventarea microcalculatoarelor, a nceput cea de-a patra generaie de calculatoare. A cincea generaie (a viitorului)

Peste 20 de ani, studenii vor nva despre cea de-a cincea (i poate a asea i a aptea) generaie de calculatoare. n momentul n care citii acest carte, n lumea 9

Aritoni Ovidiu

Sisteme de operare 1

ntreag sunt create tehnologiile necesare celei de-a cincea generaii. Oamenii de tiin din numeroase ri, inclusiv Germania, Marea Britanie, India, Japonia i Statele Unite, lucreaz la proiecte de inteligen artificial programe de calculator capabile s gndeasc similar unei fiine umane. Acest proces poate dura ani ntregi; ntruct nimeni nu tie exact cum funcioneaz inteligena uman, programele de acest gen sunt dificile de creat. n lucrul i discuiile cu privire la inteligena artificial sunt implicai oameni dintr-un numr mare de domenii, cum ar fi anatomie, biologie, informatic, educaie, matematic, filosofie i neuropsihologie. Unele descoperiri preliminare sunt deja aplicate n sistem expert i ntr-un domeniu numit logica fuzzy (fuzzy = vag ). Un alt domeniu de cercetare implic modul de construire a calculatoarelor: arhitectura sistemelor de calcul. Calculatorul von Neumann coninea un singur procesor, dar muli ingineri sunt de prere c urmtoarea generaie va cuprinde calculatoare cu prelucrare paralel care utilizeaz mai multe microprocesoare, permind astfel creterea vitezei i a eficienei. E posibil ca procesoarele viitorului s fie construite utiliznd noi materiale. n domeniul ingineriei electrice i a calculatoarelor se desfoar o competiie strns privind crearea unui supraconductor viabil. Materialele supraconductoare reprezint semiconductori care opun mult mai puin rezisten la trecerea curentului electric. O rezisten mai mic nseamn mai puin cldur, o vitez crescut i o eficien superioar. Au fost descoperite o serie de materiale care prezint proprieti supraconductoare, dar numai la temperaturi extrem de sczute, care ar face ca o zi de iarn n Artica s par incredibil de clduroas. Un supraconductor ce ar permite utilizarea la o temperatur normal ar implica nu numai o vitez mare, dar ar elimina i dispozitivele de rcire de mari dimensiuni utilizate de calculatoare pentru a disipa cldura produs de cipurile semiconductoare. O alt component a tehnologiei din generaia a cincea este dispozitivul de stocare optic. Stocarea optic utilizeaz tehnologia laser pentru scrierea i citirea informaiilor. Dispozitivele cu laser au dou avantaje: capacitatea i durabilitatea. Compact-discurile utilizate pentru stocare au o capacitate incredibil i pot conine o cantitate de informaii de mii de ori mai mare dect benzile sau discurile magnetice de aceeai dimensiune. Laserul nu atinge de fapt suprafaa discului, deci discurile optice sunt mai puin fragile dect alte forme de stocare. De fapt, dicurile optice reprezint numai nceputul: deja a fost construit prototipul unui cub de stocare optic. Acesta, similar cuburilor de stocare din filmul Star Trek, poate conine un volum de informaii de sute de ori mai mare dect discurile optice.

3.Concepte de baz
Interfaa dintre sistemul de operare i programul utilizator este definit de mulimea de instruciuni extinse pe care le furnizeaz sistemul de operare. Aceste instruciuni extinse sunt cunoscute n mod tradiional ca apeluri sistem dei ele pot fi mplementate n diverse moduri la ora actual. Pentru a nelege cu adevrat ceea ce face sistemul de operare, trebuie s examinm aceast interfa foarte ndeaproape. Apelurile sistem disponibile n interfa variaz de la un sistem de operare la altul. 10

Aritoni Ovidiu

Sisteme de operare 1

Suntem forai s facem o alegere ntre vagi generaliti (SO au apeluri sistem pentru fiiere ce pot fi citite) i cteva SO specifice (MINIX are un sistem de apeluri pentru citire cu 3 parametri: unul pentru a specifica fiierul, altul pentru a spune unde trebuie depuse datele, i altul pentru a spune ci bii trebuie citii). Am ales aadar ultima modalitate de abordare. Este mai mult de lucru n acest mod, dar aceast variant ofer detalii mai n amnunt asupra ceea ce face SO. n seciunea urmtoare vor fi dezbtute ndeaproape apelurile de sistem. Din motive de simplitate ne vom referi doar la sistemul de operare MINIX, dar majoritatea dintre apelurile de sistem UNIX corespunztoare sunt bazate pe standardul POSIX. nainte de a privi apelurile sistem, totui, merit s avem o privire de ansamblu asupra sistemului de operare UNIX, pentru a obine o idee general asupra ceea ce este un sistem de operare. Aceast privire de ansamblu se poate realiza la fel de bine i asupra sistemului de operare UNIX. Apelurile sistem se pot mpri n modul brutal n 2 categorii: prima legat de procese; a doua cu privire asupra sistemului de fiiere; Noi vom examina fiecare dintre acestea n continuare.

A. Procese
Un concept de baz n MINIX, i n toate sistemele de operare, este cel de proces. Un proces este n mod intuitiv un program n execuie. Asociat fiecrui proces este spaiul de adrese, adic o list de locaii de memorii de la un minim de obicei zero la un maxim pe care procesul poate sa le citeasca si sa le scrie. Spaiul de adrese conine programul executabil, datele programului i stiva. De asemenea asociate cu fiecare proces sunt seturile de regi inclusand programul de contabilizare ,pointerul de stiv, regitrii hardware, i orice alte informaii necesare pentru a rula un program. Ne vom ntoarce asupra conceptului de proces n detaliu n capitolul 2, dar pentru moment, cel mai simplu mod pentru a avea o bun idee intuitiv despre procese este s ne gndim la sistemele distribuite. Periodic, sistemul de operare decide oprirea rulrii unui proces i pornirea rulrii altuia, de exemplu, deoarece primul a beneficiat in ultimle secundde mai mult de procesor decat a avut dreptul . Cnd un proces a fost suspendat temporar ca acesta, el trebuie repornit mai trziu n exact aceeai form n care era cnd a fost oprit. Aceasta nseamn c toate informiile despre proces trebuie salvate explicit undeva n timpul suspendrii. De exemplu un proces are de deschis mai multe fiiere pentru citire sau scriere. Asociat cu fiecare dintre aceste fiiere este un pointer ce indic poziia curent (de exemplu numrul de bii sau articolul ce urmeaz a fi citit). Cnd un proces este suspendat temporar toi aceti pointeri trebuie salvai astfel ca un apel de citire executat dup repornirea procesului s citeasc datele corect. n multe sisteme de operare, toate informaiile despre fiecare proces, altele dect coninutul spaiilor sale de adrese, sunt stocate ntr-un tabel al sistemului de operare numit tabela proceselor, care este un tabel (sau o list nlnuit) de structuri, cte una pentru fiecare proces curent existent. 11

Aritoni Ovidiu

Sisteme de operare 1

Astfel, un proces este reprezentat de spaiile sale de adrese, numit uzual core image i tabela de intrri ale procesorului care conine regitrii alturi de alte lucruri. Ideea managementului proceselor i a apelurilor sistem este relaia dintre crearea i terminarea proceselor. S considerm un exemplu tipic. Un proces numit intrepretor de comenzi sau shell citete comenzi de la un terminal. Utilizatorul tocmai tasteaz o comand cernd ca programul s fie compilat. Shell-ul trebuie acum s creeze un nou proces ce va rula compilatoral. Cnd acel proces va termina compilarea, el va executa un apel sistem pentru a se opri. Dac un proces poate creea unul sau mai multe procese (aa numitele procese fiu) i aceste procese n aciune pot s creeze procese fiu, ajungem la un arbore al proceselor structurat ca n figura urmtoare:

B, C procese fiu ale lui A; D, E, F procese fiu ale lui B; Relaia dintre procese se bazeaz pe cooperarea care are ca scop obinerea de noi sarcini, comunicarea cu alte procese i sincronizarea aciunilor lor. Aceast comunicare se numete IPC (interprocess comunication) i va fi tratat pe larg n capitolul 2. Alt proces de apelari ale sistemului sunt disponibile pentru a solicita mai multa memorie sau a elibera memorie neutilizata ,sa astepte ca un proces subordonat sa se incheie si sa isi suprapuna programul pe unul dieferit . Uneori, exist o nevoie de a transmite o informaie la un proces n rulare care nu st n ateptarea pentru aceasta. De exemplu, un proces care comunic cu un alt proces de pe un calculator diferit trebuie s transmit mesaje n reea. Pentru a ne proteja mpotriva posibilitii ca un mesaj sau rspunsul su s fie pierdut, expeditorul poate cere sistemului de operare s l anune dup un numr specificat de secunde dac i poate retransmite procesului orice efectueaz procesul n acel timp, salvarea regitrilor si pe stiv, i pornete un semnal special pentru o procedur de tratare, de exemplu, de a retransmite semnalul presupus pierdut. Cnd semnalul de tratare este emis procesul este repornit n aceeai stare n care era nainte de primirea semnalului. Semnalele sunt analogul software al ntrruperilor hardware i pot fi generate de o serie de cauze sau de expirarea timpului. 12

Aritoni Ovidiu

Sisteme de operare 1

Multe capcane detectate de hardware, ca executarea unei instruciuni ilegale sau utilizarea unei adrese invalide, sunt convertite de asemenea n semnale de oprire a proceselor. Fiecrei persoane autorizate s utilizeze MINIX i este asociat un UID (user indentification) de ctre administratorul de sistem. Fiecare proces pornit n MINIX are UID-ul persoanei care l-a pornit. Un proces fiu are acelai UID cu al printelui. Un uid, numit super-user, are o putere special, i poate viola multe dintre regulile de protecie. n reelele mari, doar administratorul cunoate parola pentru a deveni super-user, dar muli dintre utilizatorii obinuii depun un efort considerabil pentru a ncerca s gseasc o slbiciune a sistemului care s le permit s devin super-useri fr parol.

B. Fiiere
O alt larg categorie de apeluri sistem se refer la sistemul de fiiere. O funcie major a sistemului de operare este de a ascunde particularitile discurilor i de a altor echipamente de Intrare/Ieire i de a prezenta programatorului intr-un model abstract curat si ingrijit de fisiere independente de dispozitiv . Apelurile de sistem sunt vdit intenionate s creeze, s mute, s citeasc i s scrie fiiere. nainte ca un fiier s fie citit, el trebuie s fie deschis, i dup aceasta el trebuie nchis dup citire, astfel c apelurile-sistem susin aceste lucruri. Pentru a furniza un loc unde s fie inute fiierele, MINIX are implementat conceptul de director ce desemneaz o modalitate de grupare a fiierelor mpreun. Un student de exemplu, trebuie s aib un director pentru fiecare curs la care particip, altul pentru pota electronic, i nc un director pentru propria pagin www. Apelurile sistem sunt astfel nevoite s creeze sau s mute directoare. Apelurile sistem sunt prevzute astfel ca s poat introduce sau scoate fiiere din directoare. Coninutul unui director este format de obicei din directoare i fiiere. Acest model ofer de asemenea o structur ierarhic ca n figura urmtoare:

13

Aritoni Ovidiu

Sisteme de operare 1

fig 1-6. Un sistem de fisiere pentru un departament universitar

Procesele i ierarhia de fiiere sunt organizate ca i arbori, dar similaritile se opresc aici. Ierarhia de procese nu este foarte adnc (nu are mai mult de 3 nivele), n timp ce ierarhia fiierelor are n mod uzual 4, 5 sau chiar mai multe nivele de adncime. Ierarhia proceselor are n general o via scurt, de doar cteva minute n timp ce ierarhia directoarelor poate supravieui ani de zile. Proprietile i modalitile de protecie de asemenea difer de la procese la fiiere. Uzual, doar un printe-proces poate s aib controlul sau chiar accesul la un proces-copil, dar mecanismele aproape ntotdeauna exist pentru a permite fiierelor i directoarelor s fie citite de catre un grup mai mare nu doar de catre proprietar . Fiecare fiier cu ierarhia sa de directoare poate fi specificat prin introducerea numelui cii (path name) din vrful ierarhiei de directoare, din directorul administratorului (root directory). Astfel numele cii absolute conine o list de directoare ce trebuie traversate din root directory pentru a obine fiierul, cu slash-uri ce separ componentele. Slashurile de legtur indic faptul c numele cii este absolut. La fiecare moment, fiecare proces are un director de lucru curent, n care numele cii nu ncepe cu un slash . Ca de exemplu, n ultima figur, dac /Faculty/Prof Brown ar fost directorul de lucru, atunci utilizarea numelui de cale Courses/CS101/ ar duce la acelasi fisier ca si numele de cale de ami sus . 14

Aritoni Ovidiu

Sisteme de operare 1

Procesele pot schimba directorul lor de lucru prin emiterea unui apel sistem ce specific noul director de lucru. Fiierele i directoarele sunt protejate n MINIX prin asignarea unui cod de protecie pe 9 bii. Codul de protecie conine 3 cmpuri de bii, unul pentru proprietar, unul pentru membrii grupului proprietarului i unul pentru orice alt persoan. Fiecare cmp are un bit pentru accesul n citire, un bit pentru accesul n scriere, i altul pentru accesul n execuie. Aceti 3 bii sunt cunoscui ca bii rwx. De exemplu, codul de protecie rwx r-x--x nseamn c proprietarul poate citi, scrie i executa fiierul, ali membrii ai grupului proprietarului pot s citeasc i s execute fiierul n timp ce orice alt persoan poate doar s l execute. Pentru directoare x nseamn permisiunea de cutare. O liter absolut nseamn c dreptul respectiv nu este permis. nainte ca un fiier s poat fi citit sau scris, el trebuie deschis, moment n care permisiunea este verificat. Dac accesul este permis, sistemul returneaz un ntreg mic denumit descriptor de fiier (file descriptor) pentru a-l utiliza n urmtoarele operaii. Dac accesul nu este permis, un cod de eroare este returnat. Alt concept important n MINIX este montarea sistemului de fiiere. Aproape toate PC urile au unul sau mai multe drivere de floppy-disk n care floppy-discurile pot fi inserate sau mutate. Pentru a furniza o cale simpl de a ocupa de aceste discuri amovibile (CD-ROM, floppy-disk). MINIX ofer sistemului de fiiere de pe un floppydisk s fie ataat arborelui principal de fiiere. Considerm situaia din figura urmtoare:

fig 1-7. (a) Inainte de montare fisierele de pe drive-ul 0 nu sunt accesibile (b) Dupa montare ele fac parte din ierarhia fisierelor naintare de apelul de montare (MOUNT call), discul RAM conine fiierul administratorului de sistem sau i driverul O conine floppy discul ce conine la rndul su alt sistem de fiiere. Ori de cte ori, sistemul de fiiere de pe driverul O nu poate fi utilizat se datoreaz faptului c nu exist un mod de a specifica numele cii. MINIX nu permite ca numele cii s fie prefixat de numele sau numrul unui driver.n schimb, apelurile sistem de montare permit sistemului de fiiere de pe driverul O s fie ataate sistemului de 15

Aritoni Ovidiu

Sisteme de operare 1

fiiere ale administratorului de sistem (root) oriunde decide programul ca acestea sa fie atasate . n ultima figur sistemul de fiiere de pe driverul O a fost montat n directorul b, acesta permind accesul la fiierele b/x i b/y. Dac directorul b ar fi coninut orice alte fiiere care nu ar fi fost accesibile n timp ce driverul O a fost montat, prin /b ne-am fi referit la directorul administratorului despre driverul O. Un alt concept important n MINIX este cel de fiiere speciale. Fiierele speciale fac ca dispozitivele de I/O s arate ca nite fiiere. Astefel ele pot fi citite si scrise utilizanad aceleasi apeluri sistem care sunt utilizate pentru citirea si scrierea fisierelor . Exist 2 tipuri speciale de fiiere: fiierele speciale de tip bloc (block special files); fiierele speciale de tip caracter (character special files); Fiierele speciale de tip bloc sunt utilizate pentru a modela dispozitivele constituite din colecii aleatoare de blocuri adresabile, ca de exemplu discurile. Prin deschiderea unui fiier special i citirea, s zicem a blocului 4, programul are acces direct asupra celui de-al patrulea bloc de pe dispozitiv, fr s aibe o privire asupra structurii de fiiere ce o conine. Similar, fiierele speciale de tip caracter sunt utilizate pentru imprimante, modemuri i alte dispozitive care accept un flux de caractere. Ultima trstur pe care o vom trata n aceast prezentare general este una care realizeaz legtura dintre fiiere i procese : pipe (conduct). Un pipe este un tip de pseudofiier ce poate fi utilizat pentru a conecta dou procese mpreun ca n figura urmtoare;

fig 1-8. Doua procese conectate prin pipe Cnd procesul A dorete s transmit informaii procesului B, el le scrie pe pipe aa cum ar scrie pe un fiier de ieire. Astfel comunicarea dintre procese n MINIX arat foarte mult ca fiierele obinuite pot fi citite sau scrise.In plus crearea unui apel sistem special este singurul mod in care un proces poate sa descopere ca outputul pe care scrie nu este tocmai in fisier ci in pipe .

C. Shell ul
MINIX este un sistem de operare care duce afar apelurile sistem. Editoarele, compilatoarele, ansambloarele, link-editoarele, interpretoarele de comenzi nu sunt o parte a sistemelor de operare, chiar dac sunt importante i des utilizate.Cu riscul crearii confuziei intr-o oarecare masura in acesta sectiune vom analiza pe scurt shell(interpretor) care desi nu face parte din sitemul de operare utilizeaza foarte multe parti ale acestuia si de aceea serveste ca un bun exemplu pentru modul in care pot fi utilizate apelurile sistem . 16

Aritoni Ovidiu

Sisteme de operare 1

Shellul este de asemena interfaa primar dintre utilizator ce st n faa unui terminal i sistemul de operare. Cnd orice alt utilizator se login-eaz, shell-ul este pornit. Shell consider terminalul att standard input ct i standard output. El pornete prin tastarea pe prompter a unui caracter ca un dollar ($) care spune utilizatorului c shell ul ateapt o comand. Dac se tasteaz $ date de exemplu, shell creeaz un proces fiu i ruleaz programul date ca i fiu. n timp ce procesul date ruleaz shellul l ateapt pentru a termina. Cnd procesul fiu a terminat, shell tiprete din nou prompterul i ncearc s citeasc urmtoarea line de comand. Utilizatorul poate specifica ca fiierul standard output s fie redirectat spre un fiier de exemplu: date > file Similar, fiierul standard input poate fi redirecionat aa dup cum urmeaz sort <file1> file 2 care invoc programul sort care s preia din file 1 i s trimit lui file 2. Output-ul unui program poate fi utilizat ca i input pentru alt program, conectat cu primul printr-un pipe. Astfel cat file1 file2 file3 /sort>/dev/lp invoc programul cat pentru a concatena 3 fiiere i s trimit outputul programului sort care va aranja toate liniile n ordine alfabetic. Outputul programului sort este redirectat n fiierul /dev/lp, care este un nume tipic pentru fiierele special de tip caracter pentru imprimant. (Prin convenie, toate fiierele speciale sunt reinute n directorul /dev). Dac un utilizator pune semnul & dup o comand, shell-ul nu ateapt s fie terminat comanda, i afieaz imediat prompterul utilizator. Prin urmare comanda: cat file1 file2 file3 /sort>/dev/lp & pornete sortarea fiierelor n background, n timp ce utilizatorul continu lucreze normal n paralel ce sortarea se efectueaz. Shell-ul are un numr mare proprieti interesante, dar nu avem specificul necesar dezbaterii acestui subiect aceast carte. Pentru mai multe detalii citii referinele despre shell-ul sistemului operare UNIX. s de n de

17

Aritoni Ovidiu

Sisteme de operare 1

4.Structuri de sisteme de operare

A. Sisteme monolitice

De departe, cea mai comun organizare, acestei abordri i se poate da numele de marele dezastru. Structura este aceea c nu exist structur. Sistemul de operare este scris ca i o colecie de procedeuri dintre care fiecare poate apela pe oricare din celelalte oricnd e nevoie. Cnd aceast tehnic este folosit fiecare procedur din sistem are o interfa bine definit n termeni de parametri i rezultate i fiecare este liber s apeleze oricare alt procedur dac cea din urm furnizeaz calcule folositoare de care are nevoie cea dinti. Pentru a construi programul obiect al sistemului de operare atunci cnd aceast manier este folosit trebuie s compilezi toate procedurile individual sau fiierele ce conin procedurile i apoi s le legi pe toate mpreun ntr-un singur fiier-obiect cu un link-editor. n termeni de ascundere a informaiei fiecare procedur este vizibil oricrei alte proceduri (opus unei structuri ce conine module sau pachete n care mare parte de informaie este ascuns n interiorul modulului n care doar punctele de intrare special desemnate pot fi apelate din exteriorul modulului.).

fig 1-16. Cum poate fi facut un appel sistem : (1) programul utilizator se ataseaza kernel-ului. (2) sistemul de operare determina numarul serviciului solicitat. (3) sistemul de operare apeleaza procedura de serviciu. (4) controlul se intoarce la programul utilizator

Oricum chiar n sistemul monolitic este posibil s ai o structur mic. Serviciile (apelurile sistemului) furnizate de SO sunt necesare pentru a pune parametrii n locuri bine definite ca de exemplu n registre sau pe stiv, i apoi pentru a executa o instruciune capcan special cunoscut ca Kernell-call sau apelul superviserului (superviser-call). 18

Aritoni Ovidiu

Sisteme de operare 1

Aceast instruciune schimb maina de la modul user la modul Kernel i transfer controlul la sisteme de operare, artat ca eveniment (n figura 1.16) Multe dintre CPU au dou moduri: Kernel mod pentru sisteme de operare n care toate instructiunile sunt permise i user mod pentru programele user n care I/O i alte instruciuni nu sunt permise. Apoi sistemul de operare examineaz parametrii apelrii pentru a determina care apelare trebuie efectuat. (vezi fig. 1.16) apoi, sistemul de operare indexeaz ntr-un tabel ce conine un pointer n celula K ctre procedura care efectueaz apelul sistem K. Acest operaie artat n figura 1.16 identific procedura de serviciu, care este apoi apelat. Cnd sarcina i apelul sistem sunt terminate controlul este napoiat programul user aa c poate combina executarea cu declaraia urmtorului apel de sistem. (pasul 4) Organizarea sugereaz structura de baz pentru SO: 1.Un program principal care apeleaz procedura de serviciu cerut; 2.Un set de proceduri de serviciu care ndeplinesc apelurile sistem; 3.Un set de proceduri utilitare care ajut procedurile serviciu. n acest model pentru fiecare apel sistem exist o procedur de serviciu care are grij de el. Procedeurile utilizate fac lucruri de care au nvoie cteva proceduri de serviciu ca de exemplu transmiterea datelor de la programele user. Aceast mprire a procedurilor n 3 straturi este artat n figura 16 :

fig 1-17. Un model simplu de structurare pentru un sistem monolitic

B.Sisteme stratificate
O generalizare a mamierei din fig. 1.17 este a organiza sistemele de operare ca o ierarhie de straturi, fiecare strat constuit pe cel de sub el. Primul sistem construit n acest fel a fost sistemul THE construit la Technische Hogeschool Eindhoven n Olanda de E:W: Dijkshra (1968) i studenii lui. Sistemul THE a fost un simplu sistem teanc pentru un computer olandez, Electrologica x8 care a avut 32 Kbytes i 27-bit words (bii erau cu mult napoiai). 19

Aritoni Ovidiu

Sisteme de operare 1

Sistemul avea 6 nivele aa cum este artat n figura 1.18. Nivelul O abordeaz (trateaz) repartizarea procesorului, schimbul dintre procese cnd au loc ntreruperii i expir timpii. Deasupra stratului O sistemul coninea procese secveniale, fiecare putnd fi programat fr a trebui s te ngrijorezi de faptul c mai multe procese rulau pe un singur procesor. n alte situatii stratul O permitea multiprogramarea procesorului.

fig 1-18. Structura sistemului de operare THE Stratul 1 realiza administrarea memoriei aloca spaiu pentru procesele din memoria principal i pe un cuvnt de 512 K folosit pentru a ine pri din procesele pentru care nu era spaiu n memoria principal. Deasupra nivelului 1, procesele nu erau nevoite s se ngrijoreze dac erau n memorie principal sau n memoria auxiliar (cuvnt 512 K). Softul de pe stratul 1 se asigura c paginile erau aduse n memorie oricnd era nevoie de ele. Stratul 2 asigura comunicarea dintre fiecare proces i consola operator. Deasupra acestui nivel fiecare proces avea efectiv propria lui consol. Stratul 3 avea grij de administrarea dispozitivelor de I/O i bufflerizarea streamurilor de informaii ctre i dinspre ele. Deasupra stratului 3 fiecare proces putea trata dispozitivele abstracte de I/O cu prprieti drgue n loc de dispozitive reale cu multe curioziti. Stratul 4 era locul unde se gseau programele user. Ele nu trebuiau s se ngrijoreze de proces, memorie, consol, administrare I/O. Procesele sistemelor de operare erau localizate n stratul 5. O generalizare mai ampl a conceptului de stratificare era sistemul MULTICS. n loc de straturi MULTICS era organizat ntr-o serie de inele concentrice, cele din interior fiind mai privilegiate dect cele din exterior. Cnd o procedur dintr-un inel exterior vroia s apeleze o procedur dintr-un inel interior trebuia s fac echivalentul unui apel sistem care este o instruciune-capcan (instruciune-trap) ai cror parametrii erau cu atenie verificai pentru validare nainte de a permite nceperea apelului. Dei ntregul sistem de operare era parte a spaiului adres a fiecrei proces user n MULTICS hardul fcea posibil desemnarea procedurilor individuale, memorie, segmente (momentan protejate mpotriva I/O sau executrii). n timp ce schema stratificrii sistemului THE era doar un desen ajuttor deoarece toate prile sistemului erau n cele din urm legate mpreun ntr-un singur programobiect n MULTICS mecanismul inelelor era foarte mult prezent la rulare i constrns de hard-ware. Avantajul mecanismului inelelor este c poate fi uor extins la o structur de subsisteme user. De exemplu un profesor putea s scrie un program ca s testeze programele studenilor i s ruleze acest program n nivelul N iar programele studenilor s ruleze n inelul N + 1 astfel nct s nu-i poat schimba rangul. 20

Aritoni Ovidiu

Sisteme de operare 1

C. Maini virtuale
Sistemele generate din OS/360 erau n mod strict n sisteme stratificate. Totui, muli utilizatori ai OS 360 vroiau s aib un time-sharing aa c multe grupuri att din interiorul ct i din exteriorul IBM-ului s-au decis s realizeze sisteme cu time-sharing. Sistemul time-sharing oficial al IBM, TSS/360 a fost scos pe pia trziu i cnd n cele din urm a ajuns era att de mare i ncet incat puine piee s-au convertit la el. n cele din urm a fost abandonat dup ce dezvoltarea lui a costat 50 milioane de $ (Graham 1970). Dar un grup de la centrul tinific al IBM-ului n Cambridge Massachusetts, a produs un sistem radical diferit pe care n cele din urm IBM l-a acceptat ca i produs i care este acum mult folosit pe schema lui principal. Sistemul original numit CP/CMS i mai trziu renumit VM 370 (1979) era bazat pe o ireat observaie: un sistem time-sharing ofer multiprogramare i o main extins cu o mult mai convenabil interfa dect hardul gol. Esena lui VM 360 este de a separa complet aceste 2 funcii. Inima sistemului, cunoscut ca monitorul mainii virtuale ruleaz pe hardul gol i face multiprogramarea, s furnizeze nu unul ci mai multe mainii virtuale aa cum este artat n figura 1.19. Oricum,spre deosebire de majoritatea sistemelor, aceste maini virtuale nu sunt maini extinse, cu fiiere i alte proprieti drgue. n schimb ele sunt copii exacte ale hardului dezgolit incluznd modul Kernel, modul user, dispozitivele I/ O, ntreruperi i orice altceva ce are maina real.

fig 1-19. Structura VM/370 cu CMS Deaoarece fiecare main virtual este identic cu hardul adevrat fiecare poate rula orice SO care va rula direct de pe hardul dezgolit. Diferite maini virtuale pot i fac asta frecvent, s ruleze diferite sisteme de operare. Unele ruleaz unul din descendenii lui OS/360 pentru procesare de tip stratificat sau de tip tranzacie, n timp ce altele ruleaz un singur sistem interactiv user numit CMS (Conversational Monytor System) pentru utilizatorii. Cnd un program CMS execut un pel sistem, apelul este blocat la sistemul de operare n propria sa main virtual, nu la VM 370, cum ar trebui dac ar rula pe o main real n loc de una virtual. CMS editeaz instruciuni hardware de I/O pentru a citi discul lui virtual sau pentru orice este necesar efecturii apelului. Aceste instruciuni de I/O sunt blocate de VM/370 care apoi le execut ca parte a simulrii hardului real. 21

Aritoni Ovidiu

Sisteme de operare 1

Fcnd o separare complet a funciilor multiprogramrii i furniznd o main extins fiecare din piese poate fi mult mai simpl, mai flexibil i mai uor de meninut. Ideea de main virtual este mult folosit n zilele noastre ntr-un contact diferit: rularea vechilor programe MS-DOS pe un Pentium (sau pe un alt procesor Intel pe 32 de bii.) Cnd au fost concepute Pentiumul i softul su att Intel ct i Microsoft credeau c va fi o cerere mare de rulare a vehicului soft pe noul hardware. Din acest motiv Intel a furnizat un model 8086. n acest mod maina se comport ca un 8086 (care este identic cu 8088 din punct de vedere al softului) incluznd adresarea pe 16 bii cu limit de 1 MB. Acest model este folosit de Windows OS/ i alte sisteme de operare pentru rularea programelor MS-DOS. Aceste programe sunt pornite n modul virtual 8086. Atta timp ct programele execut instruciuni normale ruleaz pe un hardware dezgolit. Oricum cnd un program ncearc s se deblocheze n sistemul de operare, s fac un apel sistem, sau ncearc s fac direct dispozitive I/O protejate, se declaneaz o deblocare n monitorul maini virtuale. Dou variante sunt posibile. La prima MS-Dosul este ncrcat pe spaiul de adres al lui 8086 virtual, astfel c monitorul main virtuale doar reflect deblocarea napoi la MS-DOS aa cum s-ar ntmpla pe un 8086 real. Cnd mai trziu MS-DOS ncearc s fac singur dispozitivele de I/O acea operaie este prins i efectuat de monitorul mainii virtuale. n alt variant monitorul mainii virtuale prinde prima deblocare i face singur dispozitivele de I/O, din moment ce tie ce sunt toate apelurile sistem MS-DOS i astfel tie ce trebuie s fac fiecare deblocare. Aceast variant este mai puin pur dect prima din moment ce doar emuleaz n mod corect din MS-DOS i nu din alte sisteme de operare aa cum face primul. Pe de alt parte este mult mai rapid din moment ce elimin problema pornirii MS-DOS ului s fac dispozitivele de I/O. Un alt dezavantaj al rulrii MS-DOS ului n modul virtual 8086 este acela c se joac cu bitul de ntrerupere 0/1 destul de mult. Nu a meritat efortul conceperii unui 8086 din moment ce maina fiind rezultat din Pentium nu este un Pentium complet. Cu un sistem VM 370 este posibil s rulezi UM 370 de unul singur ntr-o main virtual. Cu Pentium nu este posibil s rulezi un Windows ntr-o main virtual 8086 deoarece nici o versiune a Windows-ului nu poate rula pe un 8086. Un 186 este minim chiar pentru o versiune veche i emulaia 286 nu este pus la dispoziie. Cu VM 370 fiecare proces utilizator obine o copie exact a computerului actual. Cu o main virtual 8086 pe Pentium, fiecare proces utilizator obine o copie exact a unui computer diferit. Mergnd un pas mai departe, cercettorii de la M.I.T. au construit un sistem care d fiecrui utilizator o clon a computerului actual dar cu un subset de resurse. Astfel o singur main virtual obtine blocuri pe disc de la 1023, urmtoarea poate obine blocuri de la 1024 la 2047, .a.m.d. La baza stratului care ruleaz n modul Kernel este un program (numit EXOKERNEL). Funcia lui este s aloce resurse mainilor virtuale i apoi s verifice ncercrile de a le folosi pentru a se asigura c nici o main nu ncearc s foloseasc resursele altcuiva. Fiecare main virtual utilizator pe minele poate rula propriul su sisteme de operare ca i pe UM) 370 i pe Pentium-urile virtuale 8086 numai c fiecare este constrns s foloseasc doar resursele pe care le-a cerut i care i-au fost alocate. Avantajul schemei exoKernel este acela c economisete un nivel din proiect. n alte proiecte fiecare main virtual crede c are propriul su disc cu blocuri rulnd de la 0 la maxim, aa c monitorul mainii virtuale trebuie s menin tabele, s redefineasc adresele discului. (i toate celelalte resurse). Cu exoKernel aceast 22

Aritoni Ovidiu

Sisteme de operare 1

redefinire nu este necesar. ExoKernelul trebuie doar s contabilizeze crei resurse a fost atribuit maina virtual. Aceast metod nc are avantajul de a separa multiprogramarea (n exoKernel) de codul sistemului de operare user (n spaiul user) astfel nct mainile virtuale s fie separate dar totui apropiate.

D. Modelul client-server

UM / 370 ctig mult n simplitate mutnd o mare parte a codului de operare tradiional (suplementarea mainii extinse) ntr-un strat superior, CMS. Totui, VM 370 nsui este nc un program complex deoarece simularea unui 370 nu este aa de simpl (n special dac vrei s faci acest lucru eficient). Tendia n sistemele de operare moderne este de a aduce aceast idee a mutrii codului n straturile superioare, mai departe i s o ndeprteze de sistemul de operare, lsnd un Kernel minim. Maniera uzual este de a implementa majoritatea funciilor sistemelor de operare n procesele user. A cere un serviciu ca de exemplu s citeti un bloc de fiiere, un proces user (acum cunoscut ca proces client) trimite o cerere la proces client) trimite o cerere la procesul server, care apoi face munca i trimite napoi rspunsul.

fig 1-20. Modelul client-server n acest model artat n figura 1.20 tot ce face Kernelul este s asigure comunicarea dintre clieni i servere. mprind sistemele de operare n diferite pri dintre care fiecare doar se ocup de o singur faet a sistemului ca de exemplu serviciul de fiier, serviciul de proces, serviciul terminal sau serviciul de memorie, fiecare parte devine mic i uor de administrat. Mai departe pentru c toate servele ruleaz ca procese user i nu n mod Kernel nu au acces direct la hardware. Ca i consecin dac un bug este n serverul de fiiere, serviciul de fiiere se poate prbui, dar aceasta de obicei nu distruge ntreaga main. Alt avantaj al modelului client server este adaptabilitatea lui la folosirea sistemelor distribuite. Dac un client comunic cu un server trimindu-i mesaje, clientul nu e nevoie s tie dac mesajul este analizat local, sau n propria sa main sau dac a fost trimis prin reea la un server pe o main izolat. n ceea ce l privete pe client acelai lucru se ntmpl n ambele cazuri: O cerere este trimis i un rspuns se ntoarce 23

Aritoni Ovidiu

Sisteme de operare 1

fig 1-21. Modelul client-server intr-un sistem distribuit Imaginea de mai sus a Kernelului care se ocup doar de transmiterea mesajului de la clieni la servere i napoi nu este complet real. Anumite funcii ale sistemelor de operare (ca de exemplu ncrcarea comenzilor n registre fizice de I/O) sunt dificil dac nu chiar imposibil de realizat de la un program user la altul. Exist 2 ci de a trata aceast problem, una este de a avea cteva procese critice pe server (ca de exemplu driverele de intrare-ieire de fapt rulate n modul Kernel) cu acces complet la totul hardul dar care nc comunic cu alte procese folosind mecanismul normal de transmitere a mesajelor. Cealalt cale este de a construi o cantitate minim de mecanism (algoritm) n Kernel dar s lase totui deciziile de tip policy la ndemnarea servelor n spaiul user. De exemplu Kernelul ar putera recunoate c un mesaj trimis la o anumit adres nseamn s ia coninutul acelui mesaj i s l ncarce n registre de I/O pentru un disc, cu scopul de a porni citirea discului. n acest exemplu Kernelul nici mcar nu ar inspecta bii din mesaj s vad dac sunt valizi sau nu, pur i simplu i-ar copia n regitrii discului (desigur trebuie folosite anumite scheme pentru limitarea a astfel de mesaje doar ctre procesele autorizate) Desprirea dintre mecanisme i policy este un concept important i se repet continuu n sistemele de operare n diferite contexte.

24

Aritoni Ovidiu

Sisteme de operare 1

Procese

25

Aritoni Ovidiu

Sisteme de operare 1

1.Introducere

Majoritatea calculatoarelor moderne pot s efectueze n acelai timp mai multe lucruri. n timp ce ruleaz un program utilizator, calculatorul poate de asemenea s citesc de pe disc sau s afieze un text pe ecran sau la imprimant. n sistemele multiprogramare, CPU de asemenea ntrerupe program dup program, rulndu-l pe fiecare cteva sute de milisecunde. n timp ce, strict vorbind, la orice moment al timpului CPU ruleaz un singur program, n decurs de 1 secund, el efectueaz o mulime de programe, oferind iluzia utilizatorilor de paralelism. Uneori oamenii vorbesc de pseudoparalelism pentru a nelege acest schimbare nainte i napoi a CPU ntre programe, n contrast cu adevratul paralelism Hardware a sistemelor multiprocesor (care au 2 sau mai multe CPU distribuite la aceeai memorie). Activitile paralele sunt greu de efectuat de ctre oameni deoarece au consecine multiple. Prin urmare, designul SO a evoluat de-a lungul anilor la un model care face

A. Modele de procese
n acest model tot softul care ruleaz pe computer deseori incluznd i sistemul de operare este organizat ntr-un numr mare de procese secveniale sau pe scurt procese. Un proces este doar un program n execuie incluznd valorile curente ale programului de contabilizare a numrului registrele i variabilelor. Conceptual vorbind fiecare proces are propriul su procesor virtual. n realitate, desigur procesorul real se schimb napoi i nainte de la proces la proces, dar pentru nelegerea sistemului este mult mai uor s te gndeti la o colecie de procese rulnd n paralel (pseudoparalelism) dect s ncerci s ii urma felului cum un procesor se schimb de la program la program. Aceast schimbare rapid napoi i nainte este numit multiprogramare aa cum am vzut n capitolul precedent. n figura 2.1 (a) noi observm multiprogramndu-se patru programe n memorie. n figura 2.1. (b) vedem 4 procese, fiecare cu propriul su control. (Exemplu: Propriul su 26

Aritoni Ovidiu

Sisteme de operare 1

program de contabilizare), i fiecare rulnd independent unul de altul. n figura 2.1. (c) noi observm c privit dup un interval de timp au fcut procese dar la un moment dat de fapt doar un proces ruleaz.

fig 2-1. (a) Multiprogramarea a 4 programme. (b) Model conceptula a 4 procese independente,secventiale (c) In orice moment exista un singur program activ Cu un procesor trecnd napoi i nainte printre procese, rata la care un proces i realizeaz calculele nu valorific i probabil nici mcar nu poate fi reprodus dac aceleai procese ruleaz din nou. Astfel procesele nu trebuie programate cu presupuneri de timp implementate. S considerm de exemplu un proces de I/O care ncepe o poriune de program pentru a reabilita fiierele de tip back-up, execut unn ciclu de 10.000 pentru a reveni la viteza iniial i apoi genereaz o comand pentru a citi prima nregistrare. Dac procesorul decide s treac la un alt proces in timpul ciclului poriunea de proces sar putea s nu ruleze din nou dect dup ce prima nregistrare a trecut de capul de citire. Cnd un proces are cerine critice de timp real ca acesta, ca de exemplu anumite evenimente trebuie s se ntmple ntr-un numr specificat de milisecunde, msuri speciale trebuie luate pentru a fi sigur c ele se ntmpl. Oricum multe procese nu sunt afectate de multiprogramarea fundamental a procesorului, sau de viteza relativ a diferitelor procese. Diferena dintre un proces i un program este subtil dar crucial. O anaologie ne poate ajuta s clarificm aceast idee. S considerm un analist programator cu nclinaii spre gastronomie care pregtete, o prjitur pentru ziua ficei lui. Reeta pentru prjitur cu o buctorie bine dotat cu toate de intrare necesare: fin, ou, zahr, vanilie, .a.m.d. 27

Aritoni Ovidiu

Sisteme de operare 1

n aceast analogie reeta este programul (un algoritm exprimat ntr-un limbaj potrivit), programatorul este procesorul i ingredientele pentru prjitur sun datele de intrare. Procesorul este activitatea ce const in buctarul care citete reeta , aduce ingredientele i prepar prjitura. Acum imaginai-v c fiul programatorului intr n fug plngnd spunnd c a fost nepat de o albin. Programatorul nrregistreaz unde a rmas n relizarea reelei (starea procesorului curent este salvat), scoate o carte de prim ajutor i ncepe s urmeze instruciunile din ea. Aici observm cum procesorul trece de la un proces (pregtirea prjiturii) la un proces care are prioritate. (administrarea ajutorului medical) fiecare avnd un program diferit (reeta crii de prim ajutor) cnd neptura de albin a fost ngrijit, programatorul se ntoarce la prjitur de la momentul n care a rmas. Ideea cheie aici este c un proces este o activitate de un anumit fel. Are un program, date de intrare, date de ieire i un status. Un singur procesor poate fi mprit ntre cteva procese, cu un anumit algoritm scheduling fiind folosit s determine momentul opririi lucrului la un proces pentru a lucra la altul.

Ierarhia de procese
Sistemul de operare care suport conceptul de proces trebuie s furnizeze o modalitate pentru a crea toate procesele necesare. n sistemele foarte simple, sau n sistemele concepute pentru a rula doar o singur aplicaie (exemplu: controlarea unui dispozitiv n timp real), este posibil s aib toate procesele care vor fi vreodat necesare cnd sistemul este pronit. Oricum n majoritatea sistemelor este necesar o modalitate de a crea i a distruge procesele necesare n timpul operaiei. n MINIX procesele sunt create de apelul sistem fork, care creaz copia identic a procesului care apeleaz. Procesul copil poate de asemenea executa fork, deci este posibil s obin o ierarhie de procese. n alte sisteme de operare, apelurile sistem exist pentru a crea un proces, pentru a ncrca memoria, i pentru a porni rularea. Oricare ar fi natura exact a apelului sistem procesele au nevoie de o modalitate de a crea alte procese. Observai c fiecare proces are un singur printe dar zero, una, doi sau muli copii. Ca exemplu a felului cum sunt folosite ierarhile de procese, haide s ne uitm la felul cum MINIX se iniializeaz cnd pornete. Un proces special numit INIT, este prezent n boot image (imaginea de bootare). Cnd ncepe s ruleze citete un fiier spunnd cte terminale exist. Apoi genereaz un nou proces pe terminal. Aceste procese ateapt ca alte proces s se login-ieze (s se identifice). Dac un login este reuit procesul de login-are execut un apel al shellului pentru a accepta comenzi. Aceste comenzi pot s genereze mai multe procese, .a.m.d. Astfel toate procesel din ntregul sistem aprin unei singuri ierarhi, un INIT la rdcin (codul pentru INIT nu este prezentat n carte i nici shellul. Linia trebuie tras undeva.)

Strile proceselor
Dei fiecare proces nu este o entitate independent cu propriul su program de contabilizare i o stare intern deseori procesele trebuie s interacioneze cu alte procese. Un proces poate genera date de ieire pe care alt proces le poate folosi ca date de intrare. 28

Aritoni Ovidiu

Sisteme de operare 1

n comanda shell ct chapter 1, chapter 2, chapter 3/greep tree primul proces, care ruleaz ct concretizeaz i genereaz 3 fiiere. Al doilea proces, care lucreaz greep selecteaz toate liniile ce conin cuvntul tree. Depinznd de vitezele relative ale celor dou procese (care depind att de complexitatea relativ a programelor ct i dect de mult timp a avut fiecare proces), s-ar putea ntmpla ca greep s fie gata s ruleze, dar nu exist date de intrare care-l ateapt. Trebuie astfel blocat pn cnd cteva date de intrare sunt disponibile. Cnd un proces se blocheaz se ntmpl asta pentru c din punct de vedere logic el nu poate continua deoarece ateapt datele de intrare care nu sunt nc disponibile. Este de asemenea posibil ca un proces care conceptual vorbind este gata i capabil s ruleze s fie oprit deoarece sistemul de operare a decis s aloce procesorul altui proces pentru un timp. Aceste dou condiii sunt complet diferite.n primul caz suspensia este inerent n problema (nu poi procesa linia comand a utilizatorului pn cnd nu a fost tiprit.) n al doilea caz este o chestiune de tehnic a sistemului (nu sunt suficiente procesoare pentru a acorda cte unu fiecrui proces). n figura 2-2 observm o diagram a strii artnd cele trei stri n care poate fi un proces. Rulare (de fapt folosim procesorul n acel moment); Ready (pregtit de rulare care poate rula, oprit temporar pentru a lsa alt proces s ruleze); Blocat (incapabil s ruleze pn cnd anumite evenimente externe se ntmpl). Din punct de vedere logic primele dou stri sunt similare. n ambele cazuri procesul e dispus s ruleze numai ca n cea de a doua stare, temporar nu este nici un procesor disponibil pentru el. A treia stare este diferit de primele dou prin faptul c procesul nu poate rula chiar dac procesorul nu are nimic altceva de fcut. Patru tranziii sunt posibile ntre cele trei stri aa cum este artat. Tranziia 1 are loc cnd un proces descoper c nu poate continua. n unele sisteme procesul trebuie s execute un apel sistem BLOCK pentru a intra in starea blocat. n alte sisteme inclusiv MINIX cnd un proces citete dintr-un fiier special (exemple un terminal) i nu este nici o dat de intrare disponibil procesul se blocheaz automat.

fig 2-2. Un proces poate fi in stare de rulare, blocare sau pregatit. Trecerile dintre aceste stari sunt cele din figura Tranziiile 2 i 3 sunt cauzate de administratorul de procese (o parte a sistemului de operare), fr ca nici mcar procesele s tie despre ele. Tranziia 2 are loc cnd administratorul decide c procesul aflat n rulare a rulat suficient de mult i c este timpul 29

Aritoni Ovidiu

Sisteme de operare 1

s permit altui proces s aibe pentru un timp acces la procesor. Tranziia 3 are loc n toate celelalte procese a avut partea lor i este timpul ca primul proces s aib acces la procesor pentru a rula din nou. Funcia administratorului care este de a decide care proces ar trebui s ruleze cnd i pentru ct timp, este mai important. O vom analiza mai trziu n acest capitol. Muli algoritmi au fost divizai pentru a ncerca s aprecieze cererile competitive de eficien pentru sistem, astfel nct toate aceste cereri s fie ca un ntreg pentru procesele individuale. Tranziia a patra are loc cnd un eveniment extern dup care un proces atepta s se ntmple (ca de exemplu sosirea unor inputuri.) Dac nici un alt proces nu ruleaz la momentul respectiv tranziia 3 va fi pus n aplicaie i procesul va ncepe s ruleze altfel, s-ar putea s trebuiasc s atepte n starea ready pentru puin timp pn cnd procesorul este disponibil. Folosind un proces model devine mult mai uor s ne gndim la ce se ntmpl n interiorul sistemului. Unele procese ruleaz anume programul care efectueaz comenzi tiprite de un utilizator. Alte procese sunt parte dintrun sistem i se ocup de comenzi ca de exemplu: efectuarea cererilor de servicii-fiiere, sau administrarea detalilor pentru rularea unui disc. Cnd o ntrerupere a discului are loc sistemul ia decizii s opreasc rularea procesului curent i s ruleze procesul de disc care era blocat ateptnd aceea ntrerupere (de disc) . Astfel n loc s ne gndim la ntreruperi ne putem gndi la procesele user, procesele disk, procesele terminal .a.m.d. care se blocheaz cnd ateapt ca ceva s aib loc. Cnd blocul disk a fost citit sau caracterul a fost tiprit, procesul care ateapt dup el este deblocat i este disponibil s ruleze din nou. Aceast viziune d importan modelului din figura 2.3. Aici cel mai de jos nivel al sistemului de operare este administratorul (schedulerului) cu o varietate de procese deaasupra lui. Toate ntreruperile i detaliile proceselor ce pornesc i se opresc sunt ascunse n administrator care este de fapt destul de mic. Restul SO este structurat n mod atrgtor n forma unui proces. Modelulul din figura 2.3. este folosit n MINIX cu nelegerea c schedulerul (administratorul) nu nseamn doar organizarea proceselor i de asemenea i ntreruperea i comunicarea dintre toate procesele. Totui ca prim aproximare arat structura de baz.

B. Implementarea proceselor
Pentru a implementa modelul de proces, sistemul de operare menine un tabel (un tabel de structuri) numit process table, cu o intrare la fiecare proces. Aceast intrare conine informaii despre starea procesului, programul de contabilizare, pointeri de stiv, alocarea memoriei, starea fiierelor deschise, informaiile de organizare, i orice altceva despre proces ce trebuie salvat cnd procesul este schimbat de la starea de runnig la starea de ready, astfel nct s poat fi repornit mai trziu ca i cnd nu ar fi fost niciodat oprit. n MINIX administrarea proceselor, administrarea memoriei i administrarea fiierelor sunt fiecare tratate de module separate din interiorul sistemului. Astfel tabelul de procese este partiionat cu fiecare modul meninnd cnpurile de care are nevoie. Fig 2.4. are cteva dintre cele mai importante cmpuri. Cmpurile din prima coloan sunt sigurele relevante pentru acest capitol. Celelalte dou coloane sunt furnizate doar pentru a da o idee a ce informaii sunt necesare altundeva n sistem. Acum cnd c ne-am uitat la tabelul de porcese este posibil s explicm puin mai mult despre felul cum iluzia proceselor multiple secveniale este meninut pe o main cu un singur procesor si mai multe dispozitive de intrare-ieire. Ceea ce urmeaz este din punct de vedere tehnic o 30

Aritoni Ovidiu

Sisteme de operare 1

deschidere a felului cum administratorul (scheduler) din figura 2.3. lucreaz n MINIX, dar majoritarea SO moderne lucreaz n linii mari n acelai fel. Asociat cu fiecare clas de dispozitive de I/O (diskete, hard-diskuri, timeri si terminale) este o locaie lng memoria principal numit interrupt vector. Vectorul de ntrurupere (interrupt vector) conine adresele procedurii serviciului de ntrerupere. S presupunem c procesul user 3 ruleaz cnd o ntrerupere de disk are loc. Programul de contabilizare, programul de stare al proceselor, i probabil unul sau mai multe registre sunt mpinse n stiva curent de hard. Computerul sare apoi la adresa specificat n vectorul de ntrerupere. Aceasta este tot ce face hardware-ului. De aici nainte totul depinde de soft. Procedura ncepe salvnd toate registrele n intrarea tabelului de procese pentru procesul curent. Numrul procesului curent i un pointer pentru intrarea sa sunt inute n variabile globale astfel nct s fie gsite rapid. Apoi informaia depozitat de vectorul de ntrerupere este mutat din stiv, iar pointerul stivei este stabilit la o stiv temporar folosit de administratorul de procese. Aciuni ca salvarea registrului i stabilirea pointerului de stiv nici mcar nu pot fi exprimate n C aa c ele sunt executate de un mic limbaj de asamblare de rutin. Cnd aceast rutin se termin apeleaz o procedur de tip C pentru a face restul muncii. Comunicare dintre procese n MINIX este via mesaje aa c urmtoarea treapt este s construim un mesaj pentru a fi trimis la procesul disk care va fi blocat ateptndul. Mesajul spune c o ntrerupere a avut loc pentru a-l distinge de mesajele de la procesele user cernd locuri de disk pentru a fi citite i lucruri ca acesta. Starea procesului disk este acum schimbat de la starea blocat la starea ready iar schedulerul este apelat. n MINIX diferite procese au diferite prioriti pentru a da servicii mai bune controlorilor de dispozitive I/O dect procesele user. Dac procesul disk este acum procesul rulabil de cea mai mare prioritate, va fi programat s ruleze. Dac procesul care a fost ntrerupt este la fel de important sau mai mult va fi programat s ruleze din nou, i procesul disk va trebui s atepte puin timp. n oricare situaie procedura C apelat de codul de ntrerupere a limbajului de asamblare se returneaz i codul limbajului de asamblare ncarc registrele i harta memoriei pentru procesul curent i l pornete s ruleze. Controlorul i organizatorul de ntreruperi sunt schiate n figura 2.5. Nu are nici o importan c detaliile variaz uor de la un sistem la altul.

C. Thread-uri
ntr-un proces tradiional de tipul pe care tocmai l-am studiat exist un singur fir de control i un singur program de contabilizare n fiecare proces. Oricum n anumite sisteme de operare moderne suportul este furnizat pentru fire de control multiple n interiorul procesului.

31

Aritoni Ovidiu

Sisteme de operare 1

fig 2-5. Schema cu functiile sistemului de operare de nivel inferior si momentul cand apare o intrerupere Aceste fire de control sunt de obicei numite thread, sau ocazional lightweit processes (procese cu greutate uoar). n figura 2.6. se remarc 3 procese tradiionale. Fiecare are propriul su spaiu de adrese i un singur fir de control (thread). Dei n ambele cazuri noi avem 3 threaduri n figura 2.6 (a) fiecare din ele lucreaz ntr-un spaiu de adrese diferit n timp ce n figura 2.6 (b) fiecare mpart acelai spaiu de adrese.

fig 2-6. (a) Trei procese fiecare cu cate un thread (b) Un proces cu trei thread Ca exemplu unde ar putea fi folosite threaurile multiple, s considerm un proces serverfiier. El primete cereri pentru a citi i a scrie fiiere i trimite napoi datele cerute i accept datele updatate. Pentru a mbunti eficiena serverul menine o list a fiierelor recent folosite n memorie, cititind din list i scriind n list oricn este posibil. Situaia se modeleaz bine cu modelul din figura 2.6 (b). Cnd o cerere vine este nmnat unui thread pentru procesare. Dac acel thread se blocheaz ateptnd pentru un transfer de disk alte threaduri sunt nc capabile s ruleze, aa c serverul poate continua procesarea noilor cererilor chiar i n timp ce diskul de intrare-ieire are loc .Modelul din figura 2.6. (a) nu este potrivit deoarece este esenial ca toate threadurile server s acceseze aceeai list. Cele trei threaduri din figura 2.6 (b) nu mpart acelai spaiu de adrese i nu pot astfel mpri aceeasi list din memorie. Alt exemplu unde sunt folosite threaduri este n browserele pentru web ca de exemplu NETSCAPE i MOSAIC. Paginile web conin mai multe pagini mici. Pentru fiecare imagine de pe o pagin web browserul trebuie s stabileasc o conectare separat ntre home-site i cererea imaginii. O mare cantitate de 32

Aritoni Ovidiu

Sisteme de operare 1

timp este irostit stabilind i elibernd aceste legturi. Avnd multiple threaduri ntre un browser, multe imagini pot fi cerute n acelai timp, n cele mai multe cazuri, mrind considerabil eficiena din moemnt ce cu imaginile mici timpul stabilit este factorul limit nu viteza liniilor de transmitere. Cnd multiple threaduri sunt prezente n acelai spaiu de adrese cteva din cmpurile din figura 2.4. nu sunt per proces, ci per thread, aa c un tabel separat de thread-uri este necesar, cu o singur intrare per thread. Printre elementele atribuite fiecrui thread sunt programul de contabilitate, registrul i starea. Programul de contabilizare este necesar deoarece thread-urile ca i procesele pot fi suspendate i rezumate. Regitrii sunt necesari pentru ca atunci cnd threadurile sunt suspendate registrii lor trebuie salvai. n cele din urm threadurile ca i procesele pot fi n starea runnig, ready sau blocked. n anumite sisteme, sistemele de operare nu sunt contiente de threaduri cu alte cuvinte sunt administrate n ntregime n spaiul user. Cn un thread este pe punctul de a se bloca alege i pornete succesorul lui nainte de a se opri. Cteva pacehete de threaduri user- level sunt n uz, inclusiv P-threadurile POSIX i Cthreadurile. n alte cazuri, sistemul de operare este contient de existena threadurilor multiple per proces aa c atunci cnd un thread se blocheaz sistemul de operare alege pe urmtorul s ruleze fie de la acelai proces fie de la unul diferit. Pentru a face organizare Kernelul trebuie s aib un tabel de threaduri care enumer toate threadurile din sistem analog cu tabelul proceselor. Dei aceste dou alternative ar putea prea echivalente n ceea ce privete eficiena ele difer considerabil. Schimbnd threadurile este mult mai rapid cnd administrarea threadurilor este fcut n spaiul user dect atunci cnd un apel kernel este necesar. Acest fapt cere cu putere realizarea administrrii n spaiul user. Pe de alt parte threadurile administrate n ntregime n spaiul user i un thread se blocheaz (de exemplu ateptnd pentru I/O sau o greeal care trebuie rezolvat). Kernelul blocheaz ntregul proces din moment ce numai este contient c exist alte threaduri. Acest fapt cere cu putere realizarea administrrii threadurilor n kernel. Ca i consecin ambele sisteme sunt n uz i de asemenea diferite scheme hibride au fost propuse. (Anderson et al, 1992). Indiferent dac threadurile sunt administrate n kernel sau n spaiul user ele introduc o multime de probleme care trebuie rezolvate i care schimb n mod considerabil modelul programrii. S considerm efectele apelului sistem fork(). Dac procesul printe are threaduri multiple ar trebui ca i copilul s le aib. Dac nu procesul s-ar putea s nu funcioneze corect din moment ce toate pot fi importante. Oricum dac procesul-copil obine la fel demulte threaduri ca i printele ce se ntmpl dac un thread s-a blocat pe un apel ready s zicem de la tastatur. Sunt acum dou threaduri blocate de la tastatur? Cnd o linie este tiprit amndou threadurile obin o copie a liniei? Doar printele? Doar copilul? Aceeai problem exist cnd conectrile sunt deschise n reea. Alt clas de probleme are legtur cu faptul c threadurile mpart multe structuri de date. Ce se ntmpl dac un thread nchide un fiier n timp ce altul nc citete din el? S presupunem c un thread observ c exist prea puin memorie s ncepe s aloce mai mult memorie. Se ntmpl alocarea o dat sau de 2 ori? Aproape n toate sistemele care nu au fost proiectate cu threaduri, bibliotecile (ca de exemplu procedura de alocare a memoriei) nu sunt reutizabile i se vor distruge dac un al doilea apel este fcut n timp ce primul este nc activ. Alt problem se refer la raportarea greelilor. n UNIX, dup un apel sistem, starea apelului este pus ntr-o variabil global errno. Ce se ntmpl dac un thread 33

Aritoni Ovidiu

Sisteme de operare 1

face un apel sistem i nainte s fie capabil s citeasc errno alt thread face un apel sistem tergnd valoarea original? Apoi s analizm semnalele. Anumite semnale sunt din punct de vedere logic threaduri specifice, altele nu. De exemplu dac un thread apeleaz ALARM ( ) are sens ca semnalul ce rezult s mearg la threadul care a fcut apelul. Cnd Kernelul este contient de threaduri, pachetul de threaduri trebuie s in evidena semnalelor (alarmelor). Complicaie n plus pentru threadurile user-level exist cnd (ca i n UNIX) un proces poate avea doar un semnal la un anumit timp i cteva threaduri care apeleaz semnalul independent. Alte semnale ca de exemplu ntreruperea tastatur nu sunt threaduri specifice. Cine ar trebui s le recepioneze? Un thread proiectat? Toate threadurile? Un thread nou creat? Toate aceste soluii au probleme. Mai departe ce se ntmpl dac un thread schimb controlorii de semnal, fr s spun altor threaduri. O ultim problem introdus de threaduri este administrarea stivelor. Multe sisteme cnd se ntmpl s fie necesare mai multe stive, Kernelul pu i simplu furnizeaz mai multe stive. Dac Kernelul nu este contient de aceste stive nu poate n mod automat s creasc numrul lor. De fapt poate nici mcar nu realizeaz c greeala memoriei are legtur cu creterea stivelor. Aceste probleme cu siguran nu sunt reparabile, dar arat c introducerea, threadurilor ntr-un sistem existent fr o reproiectare substanial a sistemului, nu va funciona. Sintaxa pelurilor sistem trebuie redefinit i bibliotecile trebuie s fie rescrise. Toate aceste lucruri trebuie fcute n aa fel nct s rmn compatibile cu programele existente pentru cazul unui proces cu un singur thread. Pentru mai multe informaii vedei (Hauser et al, 1993, and Marsh et al, 1991).

2. Comunicarea dintre procese

Adesea procesele au nevoie sa comunice intre ele. De exemplu, intr-o instalatie, rezultatul primului proces trebuie sa fie transmis celui de-al doilea, si asa mai departe. Astfel ca exista o nevoie de comunicare intre procese si este preferabil ca acest lucru sa se faca intr-un mod bine structurat, fara intreruperi. In sectiunile urmatoare vom analiza cateva probleme legate de comunicarea interprocesorala sau IPC. Pe scurt, exista trei probleme. Prima dintre ele se refera la cele mentionate mai sus: modul in care un proces poate sa transmita informatia altui proces. Cea de-a doua problema consta in a ne asigura ca doua sau mai multe procese nu se incurca unul pe celalalt atunci cand incearca sa se angajeze in activitati critice (sa presupunem ca doua procese incearca fiecare sa obtinaultimii 100K de memorie). A treia se ocupa de succedarea corespunzatoare a proceselor atunci cand apare dependenta: daca procesul A produce date si procesul B le printeaza, B trebuie sa astepte pana A a produs cateva date inainte de a incepe sa printeze. Incepand cu sectiunea urmatoare vom analiza toate aceste probleme. 34

Aritoni Ovidiu

Sisteme de operare 1

A. Conditiile de concurenta
In unele sisteme de operare procesele care lucreaza impreuna pot sa imparta un depozit pe care fiecare poate sa scrie si sa-l citeasca. Acest depozit comun poate sa se afle in memoria principala sau poate sa fie un fisier in retea; localizarea memoriei comune nu schimba natura comunicarii sau a problemelor care apar. Pentru a vedea modul in care functioneaza, in practica aceasta comunicare interprocesorala, sa luam un exemplu simplu: un spooler de imprimanta. Cand un proces vrea sa printeze un fisier introduce numele fisierului intr-un director de spiralare. Un alt proces, daemon-ul de imprimanta, verifica periodic daca exista fisiere care trebuie printate si daca exista le printeaza si apoi le sterge numele din director. Imaginti-va ca directorul de spiralare are un numar mare (potential infinit) de sloturi, numerotate 0, 1, 2, fiecare capabil sa suporte unnume de fisier; mai inchipuiti-va ca exista doua variabile comune, out, care indica urmatorul fisier care trebuie printat si in, care indica urmatorul slot liber al directorului. Aceste doua variabile ar putea fi stocate intr-un fisier de doua cuvinte accesibil tuturor proceselor. La un moment dat, slot-urile de la 0 la 3 sunt goale (fisierele au fost deja printate), iar slot-urile de la 4 la 6 sunt ocupate (cu numele fisierelor care asteapta sa fie printate). Aproape simultan procesele A si B hotarasc ca vor sa inscrie un fisier pe lista de asteptare pentru printare. Aceasta situatie se vede in fig. 2-7. In jurisdictia in care pot fi aplicate legile lui Murphy s-ar putea intampla urmatorul lucru. Procesul A citeste in si stocheaza valoarea, 7, intr-o variabila locala numita next_free_slot. Exact in acel moment apare o intrerupere si procesorul decide ca procesul A a rulat destul si il schimba cu procesul B. procesul B citeste si el in si primeste tot 7, astfel ca stocheaza numele fisierului sau in slot-ul 7 si actualizeaza in pentru a ajunge la 8. apoi se ocupa de alte sarcini. In cele din urma, procesul A ruleaza din nou, continuand de unde a ramas. Vizualizeaza next_free_slot si gaseste 7, deci isi scrie numele fisierului in slot-ul 7, stergand numele pe care procesul B tocmai l-a pus acolo. Apoi calculeaza next_free_slot +1, care este 8, si seteaza in la 8. directorul de spiralare este acum corespunzator in interior, asa ca daemon-ul de imprimanta nu va constata nici o neregula, dar procesul B nu va obtine nici un rezultat. Situatii asemanatoare in care doua sau mai multe procese citesc sau scriu date comune si rezultatul final depinde de cel care ruleaza in momentul respectiv, se numesc conditii de competitie. Deblocarea unor programe care contin astfel de conditii nu este deloc distractiva. Testele au de cele mai multe ori rezultate bune, dar foarte rar se intampla ceva ciudat si care nu poate fi explicat.

35

Aritoni Ovidiu

Sisteme de operare 1

fig 2-7. Doua procese vor sa acceseze aceeasi memorie in acelasi timp

B. Sectiuni critice
Cum evitam conditiile de competitie? Pentru a prevenii situatiile de acest gen si multe altele care implica memoria comuna, fisierele de retea, cea mai buna metoda este este sa gasim un mod de a nu permite decat unui proces sa citeasca si sa scrie date comune. Cu alte cuvinte, avem nevoie de excludere reciproca un mod de a ne asigura ca daca unul dintre procese utilizeaza o variabila sau un fisier comun, celelalte procese nu vor avea voie sa faca acelasi lucru. Problema de mai sus a aparut datorita faptului ca procesul B a inceput sa utilizeze una dintre variabilele comune inainte ca procesul A sa fi terminat lucrul cu variabila respectiva. Alegerea operatiilor potrivite pentru realizarea excluderii reciproce este o problema de programare majora in orice sistem de operare, precum si un subiect pe care il vom analiza in amanunt in sectiunile urmatoare. Problema evitarii conditiilor de competitie poate fi formulata si intr-un mod abstract. O bucata de timp, un proces este ocupat cu calculele interne si alte lucruri care nu duc la conditii de competitie. Totusi, uneori se poate ca un proces sa acceseze fisiere sau memoria comuna, sau sa faca alte lucruri critice care pot sa duca la competitie. Acea parte a programului in care este accesata memoria comuna se numeste zona critica sau sectiune critica. Daca am putea aranja lucrurile astfel incat doua procese sa nu se afle niciodata in acelasi timp in zonele lor critice, am putea evita conditile de competitie. Desi aceasta conditie evita conditiile de competitie, nu este suficienta pentru a avea procese paralele care sa coopereze corect si eficient utilizand date comune. Pentru rezultate bune este necesara indeplinirea a patru conditii: 1. doua procese nu se pot afla in acelasi timp in zonele lor critice 2. nu se pot face presupuneri in legatura cu viteza sau numarul de procesoare 3. un proces care ruleaza in afara zonei sale critice nu poate bloca alte procese 4. nici un proces nu trebuie sa astepte foarte mult pentru a intra in zona sa critica 36

Aritoni Ovidiu

Sisteme de operare 1

C. Excludere reciproca cu asteptare activa


In aceasta sectiune vom analiza diferite propuneri de realizare a excluderii reciproce, astfel incat in timp ce un proces este ocupat cu actualizarea memoriei comune in zona sa critica, nici un alt proces sa nu intre in zona sa critica si sa faca probleme.

Dezactivarea intreruperilor
Cea mai simpla solutie este sa facem ca fiecare proces sa dezactiveze toate intreruperile imediat ce a intrat in zona critica si sa le activeze chiar inainte de a o parasi. Cu aceasta metoda nu pot aparea intreruperi cauzate de ceas. Processorul este schimbat intre procese doar ca urmare a intreruperilor produse de ceas sau din alte motive si daca intreruperile sunt dezactivate procesorul nu va fi alocat altui proces. Astfel odata ce un proces a dezactivat intreruperile, poate sa analizeze si sa actualizeze memoria comuna fara ca alt proce sa intervina. In general aceasta abordare nu este prea agreata deoarece nu este intelept sa I se acorde unui proces utilizator puterea de a dezactiva intreruperile. Sa presupunem ca unul dintre procese chiar ar face acest lucru si nu le-ar mai activa inapoi. Ar putea insemna sfarsitul sistemului. In plus, daca sistemul are doua sau mai multe procesoare, dezactivarea intreruperilor afecteaza doar procesorul care a efectuat comanda de dezactivare. Celelalte vor continua sa ruleze si vor putea sa acceseze memoria comuna. Pe de alta parte, este adesea convenabil pentru kernel sa dezactiveze intreruperile pentru cateva instructiuni in timp ce actualizeaza variabile sau liste. Daca s-ar produce o intrerupere, de exemplu intr-un moment in care lista proceselor pregatite este intr-o stare intermediara, ar putea sa apara conditii de competitie. Concluzia este urmatoarea: adesea dezactivarea intreruperilor este o tehnica utila in cadrul sistemului de operare, dar nu este potrivita ca mecanism general de excludere reciproca pentru procesele utilizatoare.

Variabile inchise
Ca o a dou-a incercare, sa cautam o solutie software. Sa zicem ca avem o singura variabila impartita,variabila (inchisa),initial 0. Cind un proces vrea sa intre in regiunea lui critica, mai intii verifica inchizatoarea. Daca inchizatoarea este 0, procesul o seteaza la 1 si intra in regiunea critica. Daca inchizatoarea . este deja 1, procesul asteapta pina ea devine 0. Deci,un 0 inseamna ca procesul este in regiunea lui critica, iar un 1 inseamna ca unele procese sunt in regiunea lor critica. Din pacate, aceasta idee contine exact acelasi (flow) fatal pe care l-am intilnit la directorul (spooler). Sa presupunem ca un proces citeste inchizatoarea. si vede ca este 0. Inainte de a seta inchizatoarea. la 1, un alt proces este programat, ruleaza, si seteaza inchizatoarea. la 1. Cind primul proces ruleaza din nou,si el la rindul lui va seta inchizatoarea la 1, si astfel doua procese vor fi in regiunea lor critica in acelasi timp. Acum puteti gindi ca am putea trece peste aceasta problema citind mai intii valoarea inchizatorii. apoi verificind-o inca o data chiar inainte de a o implementa, dar acest lucru 37

Aritoni Ovidiu

Sisteme de operare 1

chiar nu ajuta. Problema. se pune acum daca al doi-lea proces modifica inchizatoarea chiar dupa ce primul proces a terminat a doua lui verificare. Alternatii stricte

O a treia abordare a problemei este prezentata in fig.2-8. Aceasta sectiune de program, este scrisa in C. C a fost aleasa aici pentru ca adevaratele sisteme. de operare. sunt scrise toate in C ( sau C++), dar rareori in Modula 2 sau Pascal. while (TRUE) { while (turn !=0) /*wait*/; critical_region(); turn=1; noncritical_region(): } (a) while (TRUE) { while (turn !=1)/*wait*/; critical_region(); turn=0; noncritical_region(); }

(b) Fig. 2-8. O posibila solutie la pb. regiunii critice.

In Fig.2-8, variabila integer turn, initial 0, urmareste al cui rind este de a intra in regiunea critica si examineaza sau reactualizeaza memoria inpartita. Initial, procesul 0 (inspects) turn, o gaseste a fi 0, si intra in regiunea lui critica. Procesul 1 o gaseste si el a fi 0 si de aceea sta intr-un (loop) strins testind continuu turn pt. a vedea cind devine 1. Testarea continua a variabilei pina cind apare o valuare se numeste asteptarea ocupata. Normal s-ar evita, din moment ce ocupa timpul unitatii centrale de prelucrare sau a UCP sau cum vrei tuDoar atunci cind avem o asteptare motivata ca asteptarea va fi scurta este (busy waiting used). Cind procesul 0 paraseste regiunea lui critica, seteaza turn la 1, pt. a permite proc.1 sa intre in reg. lui critica. Presupunem ca procesul 1 termina reg. lui critica mai repede, deci ambele procese sunt in regiunile lor noncritice, cu turn setat la 0.Acum procsel 0 i-si executa intreg (loop) repede, revenind la regiunea lui noncritica cu turn setat la 1. In acest moment procesul 0 I-si termina regiunea noncritica si se intoarce in vf.(loop-ului). Din pacate, nu I se permite sa intre in reg. lui critica acum, pt. ca turn este 1 si procesul 1 este ocupat cu reg.lui noncritica. Altfel spus, a face ture nu este o idee prea buna cind unul din procese este mult mai incet decit celalalt. Situatia violeaza conditia 3 (..):proc.0 este blocat de catre un procf. Care nu este in reg. lui critica. Revenind la disc.despre dir (spooler), daca acum acum asociem regiunii critice citirea shi scrierea dir.(spooler), procesului 0 nu I se va permite sa printeze alt fishier pt. ca proc.1 facea altceva. Defapt, aceasta solutie cere ca cele doua procese sa alterneze strict in intrarea lor in reg. lor critice, de ex.,in fishierele(spooling). Nici unuia nu I se va permite sa (spool) doua intr-un rind. Cind acest algoritm evit toate cursele(races),nu este un candidat serios ca o solutie pt. ca violeaza conditia3.

Solutia lui Peterson

38

Aritoni Ovidiu

Sisteme de operare 1

Combinind ideea de a face ture cu ideea variabilelor inchise si a var. avertisment, un matematician (de pe pamint), T.Dekker, a fost primul care a (devise) o solutie softwere de pb. excluderii mutuale cera nu are nevoie de alternanta stricta. Vezi (Dijkstra,1965). In 1981, G.L.Peterson a descoperit un mult mai simplu mod de a ajunge la (mutual exclusion), facind astfel solutia lui Dekker depasita. Alg. Lui Peterson este ilustrat in fig. 2-9. Acest alg. Consta in doua proceduri scrise in ANSI C, ceea ce inseamna ca (function portotypes) ar trebui alimentati pentru toate functiunile definite shi folosite. Totusi, pt. a economisi spatiu,nu vom arata prototipele in acest alte exemple. Inainte de a folosi vasiabilele impartite,fiecare proces cheama regiunea de intrare cu propriul lui nr. Procesat, 0 sau 1, ca parametri. Aceasta chemare o va face sa astepte, daca este nevoie, pina este in siguranta sa intre. Dupa ce a terminat cu variabila shared, procesul cheama sau se adreseaza regiunii_de_plecare pt. a indica ca este gata,si sa lase alt proces sa intre,daca este nevoie. Sa vedem,dar, cum aceasta metoda functioneaza. Initial nici un proces nu este in regiunea lui critica. Acum procesul 0 cheama regiunea de intrare. Va ramine acolo pina interested [0] ajunge la FALSE, un evenument care se intimpla cind procesul 0 cheama regiunea de intrare aproape simultan. Amindoua vor stoca nr.lor de procesare in turn. Oricare implementare este facuta, ultima este cea care conteaza;prima este pierduta. Sa presupunem ca proc.1 implem. Ultimul, deci turn este 1. Cind amindoua proc. Ajung la declaratia while, proc. 0 se executa de 0 ori si intra in regiune lui critica. Procesul 1 (loops) si nu intra in regiunea lui critaca.

D. Repaus si repornire
Atat solutia data de Peterson cat si solutia cu utilizare TSL sunt corecte, dar ambele au defectul ca necesita asteptare activa. In principal, aceste solutii fac urmatorul lucru: cand un proces vrea sa intre in zona sa critica, verifica daca intrarea este permisa. Daca nu este, procesul ramane intr-o bucla stransa asteptand permisiunea. Aceasta abordare nu numai ca iroseste timpul procesorului, dar poate sa aiba si efecte neasteptate. Sa ne gandim la un computer cu doua procese: H, cu o prioritate ridicata si L, cu o prioritate scazuta. Regulile de temporizare spun ca H sa fie rulat de fiecare data cand este pregatit. La un moment dat, cand L se afla in zona critica, H este pregatit sa fie rulat (ex. se incheie o operatie I/O). H intra in asteptare activa, dar de vreme ce L nu este niciodata temporizat in timp ce H este rulat, L nu maiare ocazia s paraseasca zona critica, asa ca H va ramane in bucla. Aceasta situatie se mai numeste si problema inversarii prioritatii. Acum sa analizam cateva comunicari interprocesorale simple care se blocheaza in loc sa iroseasca timpul procesorului atunci cand nu li se permite accesul in zona lor critica. Una dintre cele mai simple este perechea repaus si pornire (SLEEP si WAKEUP).SLEEP este un apel al sistemului care produce blocarea apelantului, adica suspendarea lui pana cand un alt proces este pornit. Apelul WAKEUP are un parametru, pornirea procesului. Alternativ, atat SLEEP cat si WAKEUP au fiecare cate un parametru, o adresa de memorie utilizata pentru a potrivi comenzile SLEEP si WAKEUP.

39

Aritoni Ovidiu

Sisteme de operare 1

Problema producator-consumator
Un exemplu pentru modul cum acestea pot fi folosite, sa ne gandim la problema producator-consumator (cunoscuta si sub numele de buffer de legatura). Doua procese impart ace3lasi buffer de marime fixa. Unul dintre ele, producatorul, pune informatie in buffer, iar celalalt, consumatorul, scoate acesta informatie. (putem de asemenea sa generalizam problema si sa avem m producatori si n consumatori, dar vom lua cazul unui singur producator si al unui singur cosumator deoarece astfel solutia este mai simpla). Problemele apar atunci cand producatorul vrea sa puna o noua informatie in buffer, dar acesta este deja plin. Solutia este intrarea producatorului in repaus si pornirea lui atunci cand consumatorul a scos una sau mai multe informatii. In acelasi mod, in cazul in care consumatorul vrea sa scoata o informatie din buffer si constata ca buffer-ul este gol, intra in repaus pana cand producatorul introduce ceva in buffer, moment in care reporneste. Acest mod de abordare pare destul de simplu, dar duce la acelasi tip de conditii de competitie pe care le-am vazut mai devreme in cazul directorului de spiralare. Pentru a tine evidenta numarului de informatii din buffer vom avea nevoie de o variabila contul. Daca N este numarul maxim de informatii pe care le poate sustine buffer-ul, codul producatorului va verifica mai intai daca in cont se afla N informatii. Daca da, producatorul va intra in repaus; daca nu, producatorul va adauga o informatie si va mari contul. Codul consumatorului este similar: mai intai se testeaza contul pentru a se vedea daca este 0. Daca da, intra in repaus; daca este mai mare de zero, scoate o informatie si scade contul. Fiecare dintre procese verifica de asemenea sa vada daca celalalt ar trebui sa fie in repaus, si daca nu, il reporneste. Atat codul de producator cat si cel de consumator sun aratate in fig. 2-11. Pentru a exprima in C apeluri ale sistemului cum sunt SLEEP si WAKEUP le vom reprezenta sub forma de apeluri catre rutinele de biblioteca. Ele nu fac parte din biblioteca C standard, dar este foarte posibil ca ele sa fie disponibile pe orice alt sistem care efectiv a avut aceste apeluri ale sistemului. Procedurile enter_item si remove_item, care nu sunt aratate, se ocupa cu evidenta informatiilor introduse si scoase din buffer. #define N 100 int count = 0; void producer(void) { while (TRUE) { produce_item(); if (count == N) sleep(); enter_item(); count = count + 1; if (count == 1) wakeup(consumer); } } /* number of slots in the buffer */ /* number of items in the buffer*/

/* repeat forever */ /* generate next item */ /* if buffer is full, go to sleep */ /* put item in buffer */ /* increment count of items in buffer */ /* was buffer empty? */

40

Aritoni Ovidiu

Sisteme de operare 1

void consumer(void) { while (TRUE) { /* repeat forever */ if (count == 0) sleep(); /* if buffer is empty, go to sleep */ remove_item(); /* take item out of buffer */ count = count 1; /* Fig. 2-11. Problema producator-consumator cu o conditie fatala de competitie. Acum sa ne intoarcem la conditia de competitie. Acest lucru poate sa apara datorita accesului nelimitat la cont. Urmatoarea situatie ar putea sa apara. Buffer-ul este gol si consumatorul tocmai a citit contul pentru a vedea daca este 0. In acest moment temporizatorul decide sa opreasca temporar rularea consumatorului si sa inceapa rularea producatorului. Producatorul introduce o informatie in buffer, mareste contul si observa ca in acest moment are valoarea 1. Rationand ca valoarea contului era 0 si consumatorul trebuie sa fie in repaus, producatorul apeleaza wakeup pentru a reporni consumatorul. Din pacate, consumatorul inca nu este in mod logic in repaus, astfel incat semnalul de repornire este pierdut. La urmatoarea rulare a consumatorului acesta va verifica valoarea contului citit anterior , va constata ca este 0 si va intra in repaus. Mai devreme sau mai tarziu producatorul va umple buffer-ul si va intra si el in repaus. Ambele vor ramane in aceasta stare. Esenta acestei probleme este faptul ca o comanda de repornire trimisa unui proces care (inca) nu se afla in repaus este pierduta. Daca aceasta nu s-ar pierde, totul ar functiona. O remediere rapida ar fi sa se modifice regulile pentru a adauga in acest cadru un bit de repornire aflat in asteptare. Cand o comanda de repornire este trimisa unui proces care nu se afla inca in stare de repaus, acest bit este pornit. Mai tarziu, cand procesul incearca sa intre in repaus, daca acest bit este pornit va fi oprit, dar procesul va ramane pornit. Acest bit este un fel de banca pentru semnale de repornire. In timp ce in acest exemplu simplu acest bit salveaza situatia, este foarte usor de construit exemple cu trei sau mai multe procese in care doar un singur bit de acest fel este insuficient. Am putea sa facem o alta cale si sa adaugam un al doilea bit sau poate inca 8 sau inca 32, dar in principiu, problema ramane aceeasi.

E. Semafoare
Aceasta era situatia in 1965 cand E.W. Dijkstra (1965) a sugerat utilizarea unei variabile unitare pentru a numara repornirile pastrate pentru o utilizare ulterioara. In aceasta propunere a fost introdus un nou tip de variabila, numita semafoare. Un semafor putea avea valoarea 0, indicand faptul ca nu exista nici o repornire salvata; daca avea o valoare mai mare de 0 insemna ca exista una sau mai multe reporniri neefectuate. Dijkstra a propus sa existe doua operatii, DOWN si UP (generalizari pentru SLEEP, respectiv WAKEUP). Operatia DOWN la un semafor verifica daca valoarea este mai mare de 0. Daca da, ii scade valoarea (adica ii utilizeaza o repornire din cele pastrate) si continua. Daca valoarea este 0, procesul intra in repaus fara a incheia operatia DOWN pentru moment. Verificarea valorii, schimbarea ei si, posibil intrarea in repaus, totul este realizat in cadrul unei actiuni atomice unica si indivizibila. Este garantat faptul ca o operatie de semafor odata inceputa nici un alt proces nu poate sa acceseze semaforul pana 41

Aritoni Ovidiu

Sisteme de operare 1

la incheierea sau blocarea operatiei. Aceasta atomicitate este absolut esentiala pentru solutionarea problemelor de sincronizare si pentru evitarea conditiilor de competitie. Operatia UP mareste valoarea semaforului tinta. Daca unul sau mai multe procese ar fi in repaus la semaforul respectiva, incapabile sa incheie o operatie DOWN anterioara, unul dintre ele este ales de catre sistem (ex. la intamplare) si ii este permis sa isi incheie operatia DOWN. Astfel, dupa o operatie UP la un semafor unde exista mai multe procese in repaus, bariera va avea tot valoarea 0, dar va exista un proces mai putin in randul celor care se afla in repaus. Operatia de marire a valorii semaforului si repornire a unui proces este de asemenea indivizibila. Nici un proces nu se blocheaza executand o operatie UP la fel cum nici un proces nu se blocheaza in timpul unui proces de repornire in cadrul modelului anterior. Ca un fapt lateral, in lucrarea originala a lui Dijkstra acesta a utilizat numele P si V in loc de DOWN si UP, dar de vreme ce acestea nu au smnificatie mnemonica pentru oamenii care nu vorbesc limba germana (si chiar pentru cei care vorbesc aceasta limba au doar o semnificatie marginala), vom folosi termenii DOWN si UP. Acestea au fost introduse mai intai in Algol 68.

Solutionarea problemei producator-cosumator cu ajutorul semafoarelor


Semafoarele rezolva problema repornirilor pierdute, asa cum se vede in figura 2-12. este foarte important ca acestea sa fie implementate ca indivizibile. In mod normal ele se implementeaza apeluri ale sistemului, cu sistemul de operare dezactivand pentru foarte scurt timp toate intreruperile in timp ce testeaza semaforul, o actualizeaza si trece procesele in stare de repaus, daca este necesar. Deoarece toate aceste actiuni au nevoie doar de cateva instructiuni, dezactivarea intreruperilor nu cauzeaza nici o problema. Daca se utilizeaza mai multe procesoare, fiecare semafor ar trebui protejata de o variabila de blocare, utilizandu-se instructiunile TSL pentru a ne asigura ca semaforul este verificat doar de un procesor odata. Asigurati-va ca intelegeti faptul ca utilizarea TSL pentru a impiedica accesarea semaforului de mai multe procesoare in acelasi timp este diferita de asteptarea activa a producatorului sau a consumatorului ca celalalt sa umple sau sa goleasca buffer-ul. Operatia de semafor dureaza doar cateva microsecunde, in timp ce producatorul sau consumatorul ar putea dura foarte mult. #define N 100 typedef int semaphore ; semaphore mutex=1; semephore empty=N; semaphore full=0; void producer() { int item; while(true) { /* numarul de sloturi in buffer /* semafoarele sunt un tip special de intregi /*accesul controlerului in regiunea critica /*numarul sloturilor goale de pe buffer /*numarul sloturilor pline de pe buffer

/*true este constanta 1 42

Aritoni Ovidiu produce_item(&item); down(&empty); down(&mutex); enter_item(item); up(&mutex); up(&full); } }

Sisteme de operare 1 /*genereaza ceva pentru a pune in buffer /*decrementeaza variabila empty /*intra in regiune critica /*pune noul item in buffer /*paraseste regiunea critica /*incrementeaza variabila full

void consumer() { int item; while(true) /*ciclu infinit { down(&full); /*incrementeaza variabila count down(&mutex); /*intra in regiune critica remove_item(&item); /*scoate un item din buffer up(&mutex); /*paraseste regiunea critica up(&empty); /*incrementeaza variabila empty consume_item(item); /* face ceva cu itemul } } Fig. 2-12. Problema utilizator-consumator in cazul utilizarii barierelor. Aceasta solutie utilizeaza trei semafoare: unul numit full pentru numararea sloturilor pline, unul numit empty pentru numararea slot-urilor goale si unul mutex pentru a se asigura ca producatorul si consumatorul nu acceseaza buffer-ul in acelasi timp. Full este initial 0, empty este initial egal cu numarul de slot-uri din buffer, iar mutex este initial 1. Barierele care incep de la 1 si sunt utilizate de 2 sau mai multe procese pentru a se asigura ca doar unul dintre ele poate sa intre in zona sa critica la un moment dat se numesc semafoare binare. Daca fiecare proces executa o comanda DOWN chiar inainte de a intra in zona sa critica, si o comanda UP imediat dupa iesire, este garantata excluderea reciproca. Acum ca avem la dispozitie o buna comunicare iterprocesorala, sa ne intoarcem si sa analizam din nou secventa de intrerupere din fig. 2-5. intr-un sistem care utilizeaza semafoare, modul natural de a ascunde intreruperile este asocierea unui semafor, initial setata la 0, pentru fiecare dispozitiv I/O. Imediat dupa pornirea unui dispozitiv I/O, procesul administrator executa o comanda DOWN la semafor asociata, astfel blocandu-se imediat. Cand se produce intrerperea, un remediator al intreruperii executa o comanda UP la semaforul asociat, lucru care face ca procesul relevant sa fie din nou pregatit pentru rulare. In acest model, pasul 6 din figura 2-5 consta in executarea unei comenzi UP la bariera dispozitivului astfel incat la pasul 7 administratorul sa poata rula managerul dispozitivului. Bineinteles, daca in acest moment exista mai multe procese pregatite, administratorul poate sa decida rularea unui proces mai important mai intai. Modul in care se face administrarea il vom analiza mai tarziu in cadrul acestui capitol. In exemplul din fig. 2-12 am folosit semafoarele in doua moduri diferite. Aceasta diferenta este destul de importanta incat sa merite a fi explicata. Semaforul mutex este utilizata pentru excluderea reciproca. Este astfel proiectata incat sa garanteze faptul ca un 43

Aritoni Ovidiu

Sisteme de operare 1

singur proces va scrie sau va citi in buffer si variabilele asociate la un moment dat. Excluderea reciproca este necesara pentru evitarea haosului. Cealalta utilizare a semafoarelor este pentru sincronizare. Semafoarele full si empty sunt necesare pentru a garanta ca anumite secvente de evenimente apar sau nu. In acest caz ele se asigura ca producatorul nu mai ruleaza in momentul in care buffer-ul e plin si ca, de asemenea, consumatorul nu mai ruleaza in momentul cand buffer-ul e gol. Aceasta utilizare este diferita de excluderea reciproca. Desi seamfoarele sunt cunoscute de mai bine de 25 de ani, inca mai este cercetat modul in care se utilizeaza. Pentru exemplificare vezi (Tai si Carver, 1996).

E. Monitoare
Cu semafoare comunicarea interprocesorala pare usoara, nu? Nici vorba. Priviti mai atent ordinea comenzilor DOWN inaintea introducerii sau scoaterii informatiilor din buffer din fig. 2-12. Sa presupunem ca cele doua comenzi DOWN din codul producatorului ar fi in ordine inversa, astfel ca mutex ar fi scazut inainte de empty si nu dupa el. Daca buffer-ul ar fi plin, producatorul s-ar bloca, cu mutex setat la 0. In consecinta, data urmatoare cand consumatorul ar incerca sa acceseze buffer-ul ar executa o comanda DOWN la mutex, acum setat la 0 si s-ar bloca si el. Ambele procese ar ramane blocate si nu s-ar mai putea lucra nimic. Aceasta situatie nefericita se numeste impas. Vom studia impasurile in amanunt in capitolul 3. Aceasta problema este subliniata pentru a va arata cat de atenti trebuie sa fiti cand utilizati bariere. Este de ajuns o greseala mica si totul se opreste in lant. Este ca si programarea intr-un limbaj de asamblare numai ca mult mai rau deoarece greselile duc la conditii de competitie, impasuri, si alte forme de comportament neprevazut si unic. Pentru a usura scrierea corecta a programelor, Hoare (1974) si Brinch Hansen (1975) au propus un nivel mai mare de sincronizare, numit monitor. Propunerea lor era putin diferita, dupa cum se vede mai jos. Un monitor este o colectie de proceduri variabile si structuri de date, toate grupate intr-un tip special de modul sau pachet. Procesele pot sa apeleze procedurile intr-un monitor ori de cate ori doresc, dar nu pot sa acceseze direct structurile interne de date din proceduri declarate exterioare monitorului. Fig. 2-13 ilustreaza un monitor scris intr-un limbaj imaginar, pidgin Pascal. Monitor example Integer i ; Condition c; Procedure producer(x); . end; Procedure consunner(x); . .. 44

Aritoni Ovidiu . End; End monoitor; Fig. 2-13 Un monitor

Sisteme de operare 1

Monitoarele au o caracteristica importanta care le face utile pentru realizarea excluderii reciproce: un singur proces poate fi activ intr-un monitor la un moment dat. Monitoarele sunt construite ca limbaje de programare, deci compilatorul stie ca sunt deosebite si ca poate sa trateze apelurile catre procedurile monitorului altfel decat alte proceduri de apel. De obicei, cand un proces apeleaza o procedura de monitor, primele instructiuni ale procedurii vor verifica daca mai exista in mod curent vreun proces aciv in cadrul monitorului. Daca da, procesul apelant va fi suspendat pana celalalt proces paraseste monitorul. Daca nu, procesul poate sa intre. Compilatorul este cel care trebuie sa implementeze excluderea reciproca la intrarile in monitor, dar in mod obisnuit se foloseste o bariera binara. Deoarece compilatorul si nu programatorul se ocupa de excluderea reciproca este mult mai putin probabil ca ceva sa nu mearga bine. In orice caz, persoana care scrie monitorul nu trebuie sa fie constienti de modul in care compilatorul realizeaza excluderea reciproca. Este suficient sa stie ca prin transformarea zonelor critice in proceduri de monitor nu se va intampla niciodata ca doua procese sa intre in acelasi timp in zonele lor critice. Desi monitoarele furnizeaza un mod simplu de realizare a excluderii reciproce, dupa cum am vazut mai sus, acest lucru nu este suficient. Mai avem nevoie de un mod de blocare a proceselor in momentul in care acestea nu pot continua. In cazul problemei producator-consumator este destul de usor sa includem in procedurile monitorului toate testele pentru buffer, dar cum ar trebui sa se blocheze producatorul cand gaseste buffer-ul plin? Solutia consta in introducerea variabilelor de conditie, impreuna cu doua operatii WAIT si SIGNAL. Cand o procedura de monitor descopera ca nu poate merge mai departe (ex. producatorul gaseste buffer-ul plin) executa o operatie de asteptare pe o variabila de conditie, de exemplu, full. Aceasta actiune produce blocarea procesului apelant. De asemenea, permite altui proces sa intre in monitor in acest moment. Acest alt proces, de exemplu consumatorul, poate sa-si porneasca partenerul aflat in repaus executand operatiunea SIGNAL la variabila de conditie unde asteapta partenerul sau. Pentru a nu avea in monitor doua procese active in acelasi timp avem nevoie de o regula care sa stabileasca ce se intampla dupa SIGNAL. Hoare a propus sa se permita rularea procesului abia repornit si suspedarea celuilalt. Hansen a propus sa se ceara unui proces care a executat un SIGNAL sa paraseasca imediat monitorul. Cu alte cuvinte, o comanda SIGNAL poate sa apara doar ca ultima comanda intr-o procedura de monitor. Vom utiliza propunerea lui Hansen deoarece este mai simpla si mai usor de implementat. Daca operatiunea SIGNAL se executa pe o variabila de conditie pe care asteapta mai multe procese, este repornit doar unul dintre ele, cel stabilit de administratorul sistemului. Variabilele de conditie nu sunt contoare. Ele nu acumuleaza semnale pentru o utilizare ulterioara, asa cum fac barierele. Astfel daca este semnalata o variabila de conditie unde nu asteapta nici un proces, semnalul este pierdut. Comanda WAIT trebuie sa vina inaintea comenzii SIGNAL. Aceasta regula face ca implementarea sa fie mult mai 45

Aritoni Ovidiu

Sisteme de operare 1

simpla. In practica nu este o problema deoarece este usor de tinut evidenta starii fiecarui proces cu variabile, daca acest lucru este necesar. Un proces care ar executa o comanda SIGNAL poate sa vada ca acest lucru nu mai este necesar, doar consultand variabilele. O schema a problemei producator-consumator cu monitoare este data in fig.2-14 in pidgin Pascal. Poate va ganditi ca operatiile WAIT si SIGNAL arata similar cu SLEEP si WAKEUP, care, dupa cum am vazut mai devreme au dus la conditii fatale de competitie. Ele sunt foarte asemanatoare, dar cu o diferenta foarte importanta: SLEEP si WAKEUP au esuat din cauza ca in timp ce un proces incerca sa intre in repaus celalalt incerca sa-l repporneasca. Cu monitoarele acest lucru nu se poate intampla. Excluderea reciproca automata in cazul monitoarelor garanteaza ca daca, producatorul dintr-o procedura de monitor constata ca buffer-ul e plin va putea sa incheie operatia WAIT fara sa trebuiasca sa-si faca griji in legatura cu posibilitatea ca administratorul sa-l schimbe cu consumatorul chiar inainte de a incheia operatia. Consumatorului nu I se va permite nici macar accesul in monitor pana cand aceasta operatiune nu este incheiata si producatorul nu mai ruleaza. Monitor ProducerConsummer ; Condition full ,empty ; Integer count; Procedure enter; Begin If count =N then wait (full); Enter item; Count:=count+1; If count=1 then signal(empty); End; Count:=0; End monitor; Procedure producer; Begin While true do Begin Produce_item; ProducerConsumer.enter; End End; Procedure consumer; Begin While true do Begin PorducerConsumer.remove; 46

Aritoni Ovidiu Consume_item; End; End;

Sisteme de operare 1

Fig. 2-14. O schita a problemei producator-consumator cu monitoare. La un moment dat doar o procedura a monitorului poate fi activa.buffer-ul are N slot-uri. Prin marcarea automata a excluderii reciproce in ceea ce priveste zonele critice, monitoarele fac programarea paralela mult mai putin dispusa la erori decat cu bariere. Totusi, si ele au cateva puncte slabe. Nu degeaba fig. 2-14 este scrisa intr-un tip ciudat de pidgin Pascal si nu in C la fel ca celelalte exemple din aceasta carte. Dupa cum am spus si mai devreme, monitoarele sunt un concept de limbaj de programare. Compilatorul trebuie sa le recunoasca cumva si sa le aranjeze pentru excluderea reciproca. C, Pascal si majoritatea limbajelor de programare nu au monitoare, deci este anormal sa le pretindem compilatoarelor lor sa aplice vreo regula de excludere reciproca. De fapt, cum ar putea sa stie compilatorul care proceduri sunt din monitor si care nu? Aceleasi limbaje nu au nici bariere, dar adaugarea lor se face foarte usor: nu trebuie decat sa adaugi doua scurte coduri de asamblare bibliotecii pentru a emite apelurile sistem UP si DOWN. Compilatoarele nici nu trebuie sa stie de existenta acestora. Desigur, sistemul de operare trebuie sa stie de existenta barierelor, dar cel putin daca avem un sistem de operare bazat pe bariere tot se pot scrie programe utilizatoare pentru ele in C sau C++ (sau chiar BASIC daca sunteti suficient de masochist). In cazul monitoarelor aveti nevoie de un limbaj care le are incluse. Exista cateva limbaje care le au, cum este Concurrent Euclid (Holt, 1983), dar sunt foarte rare. O alta problema in ceea ce priveste monitoarele si barierele este aceea ca au fost proiectate sa rezolve problema excluderii reciproce in sisteme cu unul sau mai multe procesoare cu acces la memoria principala. Punand barierele in memoria comuna si protejarea lor cu instructiuni TSL putem sa evitam competitia. In cazul unui sistem distribuit, constand in mai multe procesoare, fiecare cu memoria sa, conectate printr-o retea locala, aceste mijloace devin inaplicabile.concluzia este ca barierele au un nivel mult prea scazut, iar monitoarele nu sunt utilizabile decat in cateva limbaje de programare. De asemenea, nici unul dintre mijloace nu asigura schimbul de informatii intre masini. Este nevoie de altceva.

F. Transmiterea mesajelor
Acest altceva este transmiterea mesajelor. Aceasta metoda de comunicare interprocesorala utilizeaza doua operatii SEND si RECEIVE, care asemeni barierelor si spre deosebire de monitoare sunt mai degraba apeluri sistem decat construcii de limbaj. Ca atare, ele pot fi usor puse in proceduri de biblioteca dupa cum urmeaza: send(destination, &message); and receive(source, &message); 47

Aritoni Ovidiu

Sisteme de operare 1

primul apel trimite un mesaj la o anumita destinatie, iar cel din urma primeste un mesaj de la o anumita sursa (sau de la orice sursa daca receptorul nu este atent). Daca nu exista nici un mesaj disponibil, receptorul se poate bloca pana soseste unul. In mod alternativ poate sa raspunda imediat printr-un mesaj de eroare.

Probleme de proiecare pentru sistemele de transmitere a mesajelor


Sistemele de transmitere a mesajelor au multe probleme care nu apar in cazul monitoarelor si barierelor mai ales daca procesele care comunica se afla pe masini diferite conectate prin retea. De exemplu mesajele pot fi pierdute de catre retea. Pentru a evita pierderea mesajelor, expeditorul si receptorul pot sa cada de acord ca imediat ce un mesaj a fost primit, receptorul va trimite inapoi un mesaj de confirmare. Daca expeditorul nu a primit acest mesaj intr-un anumit interval de timp, retransmite mesajul. Acum sa vedem ce se intampla daca mesajul propriu-zis este primit, dar confirmarea se pierde. Expeditorul va retransmite mesajul astfel incat receptorul sa-l primeasca de doua ori. Este foarte important ca receptorul sa faca deosebirea intre retransmiterea unui mesaj si un mesaj nou. De obicei aceasta problema este rezolvata prin punerea unor numere de secventa consecutive in fiecare mesaj original. Daca receptorul primeste un mesaj avand acelasi numar de secventa ca mesajul anterior, va sti ca mesajul este un duplicat si ca poate fi ignorat. Sistemele de mesaj trebuie sa rezolve si chestiunea modului in care sunt denumite procesele, astfel incat sa fie clar ce proces este specificat intr-un apel SEND sau RECEIVE. Autentificarea este o alta problema a sistemelor de mesaj: cum poate clientul sa-si dea seama daca cel cu care comunica este adevaratul server de fisier si nu un impostor? La celalalt capat al spectrumului exista de asemenea probleme importante cand expeditorul si receptorul sunt conectati la aceeasi masina. Una dintre ele este performanta. Copierea mesajelor de la un proces la altul se face tot timpul mai incet decat o operatie de bariera sau intrarea intr-un monitor. S-a lucrat mult la eficientizarea transmitarea mesajelor. Cheriton (1984) de exemplu, a sugerat limitarea marimii mesajului astfel incat acesta sa incapa in registrii masinii si apoi mesajul sa se transmita cu ajutorul registriolor.

Problema producator-consumator cu transmiterea mesajelor


Acum sa vedem modul in care problema producator-consumator poate fi rezolvata prin transmitere de mesaje si nu prin memorie comuna. O solutie este data in fig. 2-15. Presupunem ca toate mesajele sunt de aceeasi marime si ca mesajele trimise , dar neprimite inca sunt amortizate automat de catre sistemul de operare. In acest caz, este utilizat un total de N mesaje, analog numarului N de slot-uri dintr-un buffer al memoriei comune. Consumatorul incepe prin trimiterea de N mesaje goale producatorului. De 48

Aritoni Ovidiu

Sisteme de operare 1

fiecare data cand producatorul are de furnizat o informatie consumatorului, ia un mesaj gol si il trimite inapoi plin. Astfel, numarul total de mesaje din sistem ramane constant in timp, astfel incat ele pot fi stocate intr-o anumita cantitate de memorie, stiuta dinainte. Daca producatorul lucreaza mai repede decat consumatorul, toate mesajele vor sfarsi prin a fi pline asteptand consumatorul; producatorul va fi blocat asteptand ca un mesaj gol sa se intoarca. In cazul in care consumatorul lucreaza mai repede, situatia se va inversa: toate mesajele vor fi goale asteptand ca producatorul sa le umple; consumatorul va fi blocat asteptand un mesaj plin. #define N 100 void producer() { int item ; message m; while (true) { produce_item(&item); receive(consumer,&m); build_message(&m,item); send(consumer,&m); } } void consumer () { int item,I; message m; for(I=o;I<N;I++) send (prodicer,&m); while(true) { receive(producer,&m); extract_item(&m,&item); send(producer,&m); consume_item(item); } } Fig 2-15. problema producator-consumator cu N mesaje. Exista multe variante posibile in cazul transmiterii mesajului. Pentru inceput sa vedem modul in care sunt adresate mesajele. Un mod este de a atribui fiecarui proces o adresa unica si de a programa mesajele de-a se adresa proceselor. Un alt mod este sa inventam o noua structura de date numita cutie postala. O cutie postala este un loc in care se amortizeaza un anumit numar de mesaje, numar care de obicei se specifica atunci cand aceasta este creata. Atunci cand sunt utilizate cutiile postale parametrii de adresa din apelurile SEND si RECEIVE sunt cutiile postale si nu procesele. Cand un proces incearca 49

Aritoni Ovidiu

Sisteme de operare 1

sa trimita ceva unei cutii postale deja pline este suspendat pana cand un mesaj este scos din cutia postala respectiva facand loc pentru unul nou. Pentru problema producator-consumator atat producatorul cat si consumatorul vor creea cutii postale destul de mari incat sa incapa N mesaje. Producatorul va trimite mesaje continand date catre cutia postala a consumatorului iar consumatorul va trimite mesaje goale catre cutia postala a producatorului. Atunci cand sunt folosite cutii postale mecanismul de amortizare este clar: cutia postala destinatara retine mesajele care au fost trimise procesului destinatar dar care n-au fost acceptate inca. Extrema opusa cutiilor postale este eliminarea oricarei amortizari. Atunci cand acest tip de abordare este urmat, daca operatia SEND este executata inaintea operatiei RECEIVE procesul expeditor este blocat pana la incheierea operatie de primire, moment in care mesajul poate fi copiat direct din expeditor in receptor fara nici un fel de amortizare intermediara. In acelasi mod, daca operatia RECEIVE este executata mai intai receptorul este blocat pana la efectuarea operatiei de primire. Aceasta strategie este cunoscuta sub numele de rendezvous. Este mai usor de implementat decat o schema de mesaj amortizat dar este mai putin flexibila de vreme ce receptorul si expeditorul sunt obligati sa ruleze in pas de blocaj. Comunicarea interprocesorala dintre procesele utilizatoare din MINIX (si UNIX) se face prin pipes, care sunt de fapt cutii postale. Singura diferenta reala dintre un sistem de mesaj cu cutii postale si mecanism pipe este acela ca cel de-al doilea nu pastreaza limitele mesajelor. Cu alte cuvinte daca un proces scrie 10 mesaje de cate 100 bytes pentru un pipe si alt proces citeste 1000 bytes de pe acelasi pipe, cititorul va primi toate cele 10 mesaje dintr-o data. In cazul unui adevarat sistem de mesaj fiecare READ ar trebui sa returneze un singur mesaj. Bineinteles daca procesele cad de acord ca tot timpul sa citeasca si sa scrie pe pipe mesaje cu marime fixa sau sa incheie fiscare mesaj cu un caracter special, nu vor exista nici un fel de probleme. Procesele care alcatuiesc sistemul de operare MINIX utilizeaza pentru comunicarea intre ele o schema de mesaj cu mesaje de marime fixa.

3.Probleme clasice de IPC


A.Problema productorilor i consumatorilor
Se d un recipient care poate s memoreze un numr limitat de obiecte n el. Se presupune c sunt active dou categorii de procese care acceaz acest recipient: productori; consumatori. 50

Aritoni Ovidiu

Sisteme de operare 1

Productorii introduc obiecte n recipient iar consumatorii extrag obiecte din recipient. Pentru ca acest mecanism s funcioneze corect, productorii i consumatorii trebuie s aib acces exclusiv la recipient. n plus, dac un productor ncearc s acceseze un recipient plin, el trebuie s atepte consumarea cel puin a unui obiect. Pe de alt parte, dac un consumator ncearc s acceseze un recipient gol, el trebuie s atepte pn cnd un productor introduce obiecte n el. Vom prezenta mai jos o soluie cu semafoare pentru aceast problem. n acest scop vom folosi trei semafoare. 1. semafoarele plin i gol pentru sincronizarea proceselor productor i consumator; 2. semaforul mutex care asigur accesul exclusiv la recipientul de obiecte. Problema productorilor i a consumatorilor se implementeaz folosin algoritmii descrii n urmatorul program . var int n; semaphore mutex=1; semaphore gol=n; semaphore plin=0; Producator ( ) { int obiect; while (TRUE) { creeaza (obiect); P(gol); P(mutex); depune (obiect); V(mutex); V(plin); //dimensiunea recipientului de mesaje //controleaza accesul la regiunea critica //retine nr. pozitii libere din recipient //retine nr. pozitii ocupate din recipient

// produce un nou obiect obiect // decrementeaza semaforul gol // intra n regiunea critica // introduce obiectul obiect n recipient // iese din regiunea critica // incrementeaza semaforul plin

} } // Producator Consumator ( ) { int obiect; while (TRUE) { P (plin); P (mutex); extrage (obiect); V (mutex); V(gol); consuma (obiect); } } // Consumator

// decrementeaza semaforul plin // intra n regiunea critica // scoate un obiect obiect din recipient // iese din regiunea critica

//incrementeaza semaforul gol //consuma obiectul

51

Aritoni Ovidiu

Sisteme de operare 1

Programul principal: PARBEGIN Producator ( ); | Consumator ( ); PAREND

B.Problema cititorilor i a scriitorilor


Se d o resurs numit baz de date la care au acces dou categorii de procese: cititori; scriitori.

Procesele cititori acceseaz resursa numai n citire, iar scriitorii numai n scriere. Se permite ca mai muli cititori s citeasc simultan baza de date. n scimb fiecare proces scriitor trebuie s acceseze exclusiv baza de date. Vom modela soluia acestei probleme, folosind dou semafoare: un semafor bd care asigur acces exclusiv al scriitorilor la baza de date; un semafor mutex care controleaz operaiile de incrementare i decrementare a variabilei nrCit, care reine numrul de cititori activi la un moment dat.

Algoritmii dup care se lucreaz sunt prezentai n urmatorul program : var semaphore mutex=1; semaphore bd=1; int nrCit; Cititor ( ) { while (TRUE) { P (mutex); // obtine accesul la variabila nrCit nrCit=nrCit + 1; if (nrCit >=1) { P(bd); // blocheaza eventualii scriitori V (mutex); // elibereaya semaforul mutex citeste_bd ( ); // citeste baza de date P (mutex); 52

Aritoni Ovidiu nrCit = nrCit 1; if (nrCit == 0) V9bd); // elibereaza semaforul bd V (mutex); utiliz_data( ) // foloseste datele citite } } // Cititor Scriitor ( ) { while (TRUE) { creeaza_date ( ); P (bd); scrie_bd ( ); V (bd); } } // Scriitor Programul principal: PARBEGIN Scriitor ( ); | Cititor ( ); PAREND

Sisteme de operare 1

// creeaza date care vor fi introduse // obtine accesul in scriere // scrie informatia in baya de date // elibereaza accesul exclusiv la baza de date

C.Problema celor 5 filozofi


Dei insolit prin enun, este una dintre cele mai cunoscute probleme de concuren. La o mas rotund stau 5 filozofi, care au doar dou misiuni: - s mnnce; - s mediteze. Fiecare filozof are n stnga i n dreapta lui cte o furculi, partajat cu vecinul su, din partea respectiv. Cnd un filozof dorete s mnnce, ncearc s ia cele dou furculie. Dac una dintre ele este folosit de un vecin al su, filozoful va trebui s atepte. UN filozof mnnc numai cnd are ambele furculie, dup care le pune din nou pe mas i i reia operaia de meditare. n aceast problem, procesele sunt filozofii, iar resursele accesate sunt furculiele. Soluia problemei filozofilor urmrete evitarea a dou situaii nedorite:

53

Aritoni Ovidiu impasul apare dac un filozof ateapt la nesfrit obinerea unei furculie. infometarea (2.4.2)

Sisteme de operare 1

apare dac accesarea furculielor se face inechitabil ntre cei 5 filozofi. De exemplu, urmtoarea soluie poate conduce la impas, cnd doi filozofi vecini ncearc s obin o furculi ocupat de cellalt. Fiecare dintre ei ocup mai nti furculia din stnga pe care nu o mai ced, dup care o solicit pe cea din dreapta, care este deja ocupat. Aciunile celor 5 filozofi sunt descrise n urmatorul program : Filozof (ind) { Resursa furcSt, furcDr; While (TRUE) { Gandeste ( ); ObtineRes (furcSt); ObtineRes (furcDr); Mananca ( ); ElibRes (furcSt); ElibRes (furcDr); } } // Filozof // ind indicele filozofului

Programul principal: PARBEGIN Filozof (1); | Filozof (2); | Filozof (3); | Filozof (4); | Filozof (5); PAREND Soluii posibile pentru rezolvarea impasului: Dac un filozof nu poate obine i furculia din dreapta, atunci elibereaz furculia din stnga i ncearc mai trziu (folosind aceast soluie se poate ajunge la nfometare). Un singur filozof s mnnce la un moment dat (serializare). Obinerea ambelor furculie printr-o operaie atomic, ceea ce poate conduce la nfometarea de exemplu a filozofului 2, dac filozofii 1 i 3 nu gndesc nici o dat n acelai timp. Programul urmator d soluie corect, n care gestiunea furculielor este realizat centralizat de ctre procesul server ResServer. Programul principal rmne cel de mai sus. var nrFil = 5; // numarul de filozofi stare [nrFil] // intrarile pot fi: INFOMETAT, MANANCA, GANDESTE semaphore self [ ] = {1,1,1,1,1}; // semafoare binare asociate 54

Aritoni Ovidiu semaphore multex = 1;

Sisteme de operare 1 // pentru acces exclusiv

ResServer ds; // procesul server care gestioneaza furculitele Filozof (id) { // procedura asociata folozofului cu indicele id Ds. obtineFurc (id); mananca ( ) ds. elibFurc (id); } // Filozof int dreapta (int i) { return (nrFil + i 1) % nrFil; } // dreapta int stanga (int i) return (i + 1) } // stanga { % nrFil;

obtineFurc (int i) { P (mutex); stare [i] = INFOMETAT; test (i); // verific dac vecinii filozofului i nu se afl starea // MANACA - > caz n care filozoful i primete cele dou // furculie i trece din starea INFOMETAT n starea // MANANCA, astfel ateapt ndeplinirea condiiei respective V (mutex); P (self [i]); } // obtineFurc elibFurc (int i) { P (mutex); stare [i] = GANDESTE; test (stanga (i)); test (dreapta (i); V (mutex); } // elibFurc test (int k) { P (mutex); stare [i] = GANDESTE; test (stanga (i)); test (dreapta (i)); V (mutex); } // elibFurc 55

Aritoni Ovidiu test (int k) { if (stare [stanga (k)] ! = MANANCA & & stare [dreapta (k)] ! = MANANCA & & stare [k] = = INFOMETAT) { stare [k] = MANANCA; V (self [k] ); } } // test

Sisteme de operare 1

D.Problema frizerului
Acest problem porneter de la urmtoarele ipoteze: un frizer tunde pe rnd mai muli clieni; un client intr n frizerie, dac aceasta este plin el pleac, altfel i ateapt rndul la tuns; dac nu mai sunt clieni, frizerul doarme i este trezit de urmtorul client care dorete s fie tuns; Considerm c iniial frizerul doarme i este trezit de primul cilent venit. Programul urmator prezint o soluie acestei problemei. var semaphore semf = 0; semaphore semf = 1; int nrCl = n; semaphore mutex; Client ( ) { P (mutex); if (nrCl + 1<=n) { nrCl = nrCl + 1; V (semf); } else { V (mutex); exit ( ); } V (mutex); P (semp); } // Client

// semafor asociat frizerului // semafor asociat unui client // numar maxim de clieni care pot a;tepta // pt. acces exclusiv la variabile

// anun frizerul c dorete s fie tuns

// i ateapt rndul

56

Aritoni Ovidiu Frizer ( ) { while (true) { P (semf); P (mutex); nrCl = nrCl 1; V (mutex); V (semp); } } // Frizer

Sisteme de operare 1

// ateapt un client // l tunde // cheam urmtorul clent

Programul principal: int n= 10; PARBEGIN Frizer ( ); Client ( ); | Client ( ); | Client ( ); . . . | Client ( ); | Client ( ); PAREND Programul 2.5. Problema frizerului

4. Administrarea proceselor
In exemplele din sectiunile anterioare am intalnit deseori situatii in care doua sau mai multe procese (ex. producator si consumator) puteau fi, in mod logic, rulate pe computer. Atunci cand mai mult de un proces poate fi rulat, sistemul de operare trebuie sa decida care este primul pe care il rulaeza. Partea din sistemul de operare care hotaraste acest lucru se numeste temporizator, iar algoritmul pe care il foloseste se numeste algoritm temporizator. Demult, cand sistemele de incarcare aveau intrari sub forma de imagini inregistrate pe o banda magnetica, algoritmul temporizator era simplu: pur si simplu ruleaza urmatoarea sarcina de pe banda. In cazul sistemelor legate in retea algoritmul temporizator este mult mai complex deoarece exista adesea mai multi utilizatori care solicita serviciile computerului, la fel cum pot exista simultan mai multe fluxuri de incarcare (ex. intr-o firma de asigurari pentru procesarea cererilor). Chiar si pe un computer personal pot exista mai multe procese initiate de catre utilizator, procese care deja solicita procesorul, ca sa nu mai vorbim de sarcinile de fond cum sunt reteaua sau posta electronica primind sau trimitand mesaje. 57

Aritoni Ovidiu

Sisteme de operare 1

Inainte de a analiza anumiti algoritmi de temporizare trebuie sa ne gandim care este functia temporizatorului. Sa nu uitam, temporizatorul trebuie sa decida ordinea si nu sa furnizeze mecanismul. Exista mai multe criterii care trebuie sa fie intrunite de un bun algoritm de temporizare. Dintre acestea amintim: 1. Echitabilitatea - asgurati-va ca toate procesele folosesc parti egale din procesor. 2. Eficienta - procesorul trebuie sa lucreze tot timpul la intreaga sa capacitate. 3. Timpul de raspuns - micsorarea timpului de raspuns pentru fiecare utilizator interactiv. 4. Confirmarea raspunsului - micsorarea timpului in care utilizatorii care introduc date primesc rezultatul. 5. Viteza de lucru - marirea numarului de sarcini efectuate intr-o ora. Daca va ganditi putin veti constata ca unele dintre aceste criterii sunt contradictorii. Pentru a micsora timpul de raspuns pentru utilizatorii interactivi temporizatorul ar trebui sa nu ruleze nici o sarcina de incarcare (poate doar intre orele 3 a.m. si 6 a.m. cand toti utilizatorii interactivi dorm). Totusi, utilizatorii care doresc sa introduca date nu vor agrea, probabil, acest algoritm deoarece este in contradictie cu punctul 4. Se poate demonstra ca orice algoritm de temporizare ce avantajeaza o anumita categorie de sarcini defavorizeaza automat alta. La urma urmei timpul disponibil al procesorului este limitat. Pentru a da mai mult unui utilizator trebuie sa-i dai altuia mai putin. Asa e viata. O problema pe care temporizatoarele trebuie sa o rezolve este faptul ca fiecare proces este unic si imprevizibil. Unele pierd mult timp asteptand dupa fisiere I/O in timp ce altele ar utiliza procesorul cat mai mult timp posibil. Cand temporizatorul incepe sa ruleze un proces nu se stie peste cat timp procesul respectiv se va bloca fie pentru I/O, fie la o bariera, fie din alte motive. Pentru a se asigura ca nici un proces nu ruleaza pentru prea mult timp, aproape toate computerele au incorporat un cronometru sau un ceas electronic care intrerupe periodic procesele. In general frecventa este de 50 sau 60 de ori pe secunda (50 sau 60 Hertz, prescurtat Hz), dar la multe computere sistemul de operare poate fi acela care seteaza aceasta frecventa. La fiecare intrerupere sistemul de operare ajunge sa ruleze si sa decida daca procesul care ruleaza in momentul respectiv trebuie sa continue sau daca a beneficiat de procesor destul timp si, pentru moment alt proces trebuie sa utilizeze procesorul. Aceasta strategie de a suspenda temporar procesele care pot fi rulate se numeste temporizare preemptiva si este in opozitie cu metoda "ruleaza pana la capat" utilizata de vechile sisteme de incarcare, metoda care se mai numeste si programare non-preemptiva. Dupa cum am vazut in acest capitol, un proces poate fi suspendat intr-un moment arbitrar, fara nici un avertisment, pentru ca alt proces sa poata fi rulat. Acest lucru creaza conditii de competitie astfel ca barierele, ferestrele, mesajele, precum si alte metode mai sofisticate devin necesare pentru a preveni aceasta situatie. Pe de alta parte, daca un proces ar fi lasat sa ruleze fara intreruperi pana la sfarsit ar insemna ca un proces care calculeaza valoarea lui PI cu un miliard de zecimale ar bloca rularea altor procese pentru un timp nelimitat. Astfel, desi algoritmii de temporizare non-preemptiva sunt simpli si usor de implementat, ei nu sunt folositi in general pentru sisteme obisnuite cu mai multi utilizatori simultan. Pe de alta parte, pentru sisteme dedicate, asa cum este un server pentru baza de date se poate ca procesul principal sa initieze un proces secundar care 58

Aritoni Ovidiu

Sisteme de operare 1

lucreaza pentru o solicitare si sa-l lase sa ruleze pana la final sau pana se blocheaza. Diferenta dintre acest tip de sistem si sistemele obisnuite este aceea ca intr-un sistem pentru baze de date toate procesele sunt controlate de acelasi stapan care stie ce va face fiecare subordonat si cat va dura procesul respectiv.

A. Administrarea circulara
Acum haideti sa analizam cateva tipuri particulare de algoritmi de administrare. Unul dintre algoritmuii cei mai vechi, mai simpli si mai echitabili, precum si cel mai utilizat este cel circular. Fiecarui proces ii este alocat un interval de timp, numit quantumul sau, timp in care ii este permis sa ruleze. Daca la sfarsitul acestui interval procesul inca ruleaza, procesul este interrupt si procesorul alocat altui proces. Daca procesul s-a blocat sau s-a incheiat inaintea timpului alocat, comutarea procesorului se face desigur, in momentul blocarii. Acest tip de temporizare este foarte usor de implementat. Tot ce are de facut temporizatorul este sa mentina o lista de procese care pot fi rulate, asa cum se vede in fig. 2-22(a). Atunci cand procesul si-a utilizat timpul alocat trece la sfarsitul listei, ca in fig. 2-22(b).

fig. 2-22. Temporizarea circulara. (a) Lista proceselor care pot fi rulate (b) Lista proceselor care pot fi rulate dupa ce B si-a folosit timpul alocat. Singurul punct interesant in ceea ce priveste temporizarea circulara este lungimea quantumului. Comutarea de la un proces la altul necesita un anumit timp pentru ca trebuie salvati si incarcati registrii si schemele de memorie, actualizate diferite liste si tabele, etc. Sa presupunem ca aceasta schimbare de proces sau schimbare de context, cum se mai numeste, dureaza 5 msec. Sa presupunem de asemenea ca avem un quantum setat la 20 msec. Cu acesti parametri, dupa 20 de msec. de lucru util, procesorul trebuie sa faca schimbarea de proces in 5 msec., astfel, douazeci la suta din timpul procesorului va fi irosit pentru sarcini administrative. Pentru a mari eficienta procesorului am putea sa setam quantumul la 500 msec., de exemplu. Acum, timpul pierdut nu trece de 1 procent. Dar ganditi-va ce se intampla intr-un sistem legat la server daca 10 utilizatori interactivi apasa tasta pentru furnizarea rezultatelor aproximativ in acelasi timp. Zece procese vor fi adaugate pe lista proceselor care pot fi rulate. Daca procesorul nu lucreaza, primul proces va incepe imediat, cel de-al 59

Aritoni Ovidiu

Sisteme de operare 1

doilea o jumatate de secunda mai tarziu, si asa mai departe. Cel care are ghinionul sa fie ultimul poate sa fie nevoit sa astepte 5 secunde pana sa aiba ocazia sa inceapa, presupunand ca toti ceilalti isi folosesc integral quantumul. Majoritatea utilizatorilor vor fi de parere ca este mult prea mare un interval de 5 secunde pentru a raspunde la o comanda simpla. Aceeasi problema poate sa apara la un computer personal care suporta multiprogramarea. Concluzia poate fi formulata astfel: setarea unui quantum prea scurt mareste numarul de schimbari de procese si diminueaza eficienta procesorului, dar daca acest quantum este prea mare poate duce la o intarziere prelungita a raspunsului pentru comenzile scurte interactive. Un quantum de 100 msec. este adesea un compromis rezonabil.

B. Administrare prioritara
Administrarea circulara presupune, implicit ca toate procesele au aceeasi importanta. Adesea, cei care detin si opereaza computere cu mai multi utilizatori nu sunt de aceeasi parere.La universitate ordinea importantei este: intii decanul, apoi profesorii, secretarele, portarul si in sfarsit, studentii.Necesitatea de a lua in considerare factori externi duce la temporizarea prioritara. Ideea principala este urmatoarea: fiecarui proces ii este atribuita o anumita importanta, iar procesul cu cea mai mare importanta este cel care va rula. Chiar si pe un computer cu un singur utilizator pot exista mai multe procese, unele mai importante decat altele. De exemplu, un program de fond care trimite emailuri ar trebui sa aiba o mai mica importanta decat un proces care afiseaza pe ecran un film video in timp real. Pentru ca procesele cu o importanta ridicata sa nu ruleze la nesfarsit, temporizatorul poate sa scada importanta procesului care ruleaza in momentul respectiv odata cu fiecare intrerupere a cronometrului. Daca aceasta scadere a importantei il face sa fie mai putin important decat urmatorul proces de pe lista se produce o schimbare de procese. In acelasi timp, fiecarui proces ii poate fi alocat un quantum maxim in care poate sa utilizeze procesorul fara intrerupere. La sfarsitul acestui quantum, urmatorul proces de pe lista incepe sa ruleze. Importanta proceselor poate fi atribuita static sau dinamic. Pe un computer militar procesele initiate de catre generali pot porni cu importanta de 100, cele initiate de colonei - 90, maiori - 80, capitani - 70, locotenenti - 60, si asa mai departe. In acelasi timp, la un centru commercial de computere, cele mai importante lucrari ar putea costa 100 de dolari pe ora, cele de importanta medie - 75 de dolari pe ora, iar cele cu o importanta scazuta 50 de dolari pe ora. Sistemul UNIX are o comanda, nice, care permite, la cererea utilizatorului, scaderea importantei procesului sau pentru a fi amabil cu ceilalti. Nimeni nu-l foloseste niciodata. Prioritatea poate fi atribuita dinamic de catre sistem pentru a indeplini diferite functii ale sistemului. De exemplu, unele procese sunt strans legate de I/O si in cea mai mare parte a timpului asteapta finalizarea I/O. De fiecare data cand un astfel de proces solicita procesorul, acesta ar trebui sa-i fie cedat imediat, pentru a-i permite sa initieze urmatoarea comanda I/O, care poate continua in paralel cu alt proces. Daca procesul de legatura I/O asteapta mult timp dupa procesor inseamna ca el va ocupa memoria mai mult 60

Aritoni Ovidiu

Sisteme de operare 1

timp decat este necesar. Un algoritm simplu care confera o buna efectuare a proceselor de legatura I/O este setarea prioritatii pe 1/f, unde f reprezinta raportul ultimului quantum utilizat de un proces. Un proces care a folosit doar 2 msec. din cele 100 alocate va primi o prioritate de 50, in timp ce un proces care a rulat timp de 50 msec. inainte de a se bloca va primi prioritate 2, iar un proces care a utilizat quantumul in intregime va primi prioritate 1. Adesea este mult mai convenabil sa se grupeze procesele in clase de prioritati si sa se utilizeze temporizarea prioritara intre clase si temporizarea circulara in cadrul fiecarei clase. Figura 2-23 ne arata un sistem cu 4 clase de prioritati. Algoritmul de temporizare este urmatorul: atata timp cat exista in clasa 4 de prioritati procese care pot fi rulate, sa se ruleze fiecare un quantum, dupa metoda circulara, neluand in seama clasele cu o prioritate mai mica. Daca in clasa 4 nu exista nici un proces, sa se ruleze procesele din clasa 3 de prioritati, tot in mod circular. Daca atat clasa 4 cat si clasa 3 sunt goale, vor rula procesele din clasa 2 dupa metoda circulara, si asa mai departe. Daca, din cand in cand prioritatile nu sunt modificate, procesele cu o mica prioritate pot sa moara acolo.

fig. 2-23. Un algoritm de temporizare cu 4 clase de prioritati.

C. Randuri multiple
Unul dintre primele temporizatoare prioritare a existat in CTSS (Corbato si al. 1962). Problema intampinata de CTSS a fost aceea ca schimbarea proceselor era foarte inceata din cauza ca 7094 nu putea memora decat un singur process o data. Fiecare comutare insemna trecerea pe discheta a procesului curent si citirea de pe disk a unui nou proces. Cei care au proiectat CTSS si-au dat repede seama ca era mai eficient sa se dea proceselor legate de procesor un quantum mai mare din cand in cand decat quantumuri mici si frecvente (pentru a reduce numarul schimbarilor). Pe de alta parte, un quantum mare pentru toate procesele ar duce la cresterea timpului de raspuns, dupa cum am vazut deja. Solutia lor a fost formarea claselor de prioritati. Procesele din clasele superioare erau rulate un quantum. Procesele din clasele urmatoare - doua quantumuri, urmatoarele, patru quantumuri, si asa mai departe. De fiecare data cand un proces isi epuiza quantumurile alocate era mutat o clasa mai jos. De exemplu, ganditi-va la un proces care avea nevoie sa calculeze 100 de quantumuri fara intrerupere. Initial ii era acordat un quantum, apoi era schimbat. Data 61

Aritoni Ovidiu

Sisteme de operare 1

urmatoare ii erau acordate doua quantumuri inainte de a fi schimbat. La rulari succesive ar fi obtinut 4,8,16,32 apoi 64 de quantumuri, desi ar fi folosit pentru a-si termina sarcina doar 37 de quantumuri din cele 64 finale. In acest caz ar fi nevoie numai de 7 schimbari (incluzand si incarcarea initiala) in loc de 100 in cazul unui algoritm circular pur. In plus, pe masura ce procesul se adancea tot mai mult in randuri prioritare, ar fi rulat din ce in ce mai rar, pastrand procesorul pentru procese scurte, interactive. Urmatoarea tactica a fost folosita pentru a evita uitarea proceselor care initial necesitau o rulare indelungata, dar care ulterior, au devenit interactive. De fiecare data cand la un terminal se cerea finalizarea, procesul apartinand terminalului respectiv era mutat in clasa cu cea mai mare importanta, presupunandu-se ca procesul este pe cale sa devina interactiv. Intr-o zi un utilizator cu un proces solicitant pentru procesor a descoperit ca simpla apasare a tastei ENTER aleatoriu, o data la cateva secunde scurta foarte mult timpul de raspuns. Le-a spus tuturor prietenilor lui. Morala povestii: e mult mai usor sa faci un lucru bine teoretic decat in practica. Multi alti algoritmi au fost utilizati pentru impartirea proceselor in clase de prioritati. De exemplu, sistemul XDS 940 (Lampson, 1968), construit in Berkeley, avea 4 clase de prioritati numite terminal, I/O, quantum scurt si quantum lung. Cand un proces care astepta pentru intrare de terminal era in cele din urma initiat, acesta intra in clasa cu cea mai mare imprtanta (terminal). Cand un proces care astepta pentru disk era pregatit, intra in cea de-a doua clasa. Cand un proces rula inca in momentul terminarii quantumului, acesta era initial plasat in cea de-a treia clasa. In orice caz, daca un proces isi epuiza integral quantumul de prea multe ori consecutiv, fara sa se fi blocat pentru terminal sau alt I/O, era mutat in capatul randului. Multe alte sisteme folosesc ceva similar pentru a favoriza utilizatorii si procesele interactive fata de cele de fond.

D. Intai sarcinile cele mai scurte


Majoritatea algoritmilor de mai sus au fost conceputi pentru sisteme interactive. Haideti sa analizam acum unul care este potrivit in special pentru sarcini de incarcare a caror timp de rulare este cunoscut dinainte. Intr-o companie de asigurari de exemplu, oamenii pot sa prevada destul de exact cat timp va fi necesar pentru a rula o incarcare de 1000 de cereri, de vreme ce o munca similara se face in fiecare zi. Atunci cand mai multe sarcini la fel de importante formeaza un rand la intrare asteptand sa fie incepute, temporizatorul ar trebui sa foloseasca algoritmul "intii sarcinile cele mai scurte". Priviti figura 2-24. Vom vedea 4 sarcini A,B,C si D cu timpuri de rulare de 8,4,4 si respectiv 4 minute. Rulandu-le in aceasta ordine, raspunsul pentru A va veni in 8 min, pentru B in 12, pentru C in 16, iar pentru D in 20 de minute, deci o medie de 14 minute.

fig.2-24. Un exemplu de temporizare de tipul "intii sarcinile cele mai scurte" 62

Aritoni Ovidiu

Sisteme de operare 1

Acum haideti sa analizam cazul in care aceste patru sarcini sunt rulate cu ajutorul algoritmului " intii sarcinile cele mai scurte", asa cum vedem in figura 2-24(b). Timpurile de raspuns sunt acum de 4,8,12 si 20 de minute, deci o medie de 11 minute. S-a dovedit ca aceasta metoda este cea mai buna. Sa presupunem ca exista patru sarcini cu timpuri de rulare de a,b,c respectiv d. Prima sarcina este incheiata in intervalul de timp a, cea de-a doua in intervalul a+b si asa mai departe. Media de raspuns va fi de (4a+3b+2c+d)/4. Este clar ca a contribuie mai mult la medie decat in alte cazuri, deci a trebuie sa fie cea mai scurta sarcina, urmata de b, apoi de c si in cele din urma d deoarece ea fiind cea mai lunga sarcina va afecta doar timpul ei de raspuns.Acelasi argument este valabil pentru un numar oricat de mare de sarcini. Dat fiind ca acest algoritm da cea mai mica medie a timpului de raspuns ar fi bine daca ar putea fi folosit si pentru procesele interactive. Pana la un anumit punct pot fi folosite. In general, procesele interactive urmeaza modelul de asteptare a comenzii, executarea comenzii, si asa mai departe. Daca privim executarea fiecarei comenzi ca pe o sarcina separata, atunci, in ansamblu, putem sa micsoram timpul de raspuns daca rulam prima data cea mai scurta sarcina. Singura problema este sa ne dam seama care este cel mai scurt dintre procesele curente care pot fi rulate. O abordare posibila ar fi sa facem estimari bazate pe fapte anterioare si sa rulam procesul care are cel mai scurt timp estimat. Sa presupunem ca pentru un terminal timpul estimat pentru o comanda este T0. Acum sa presupunem ca urmatoarea rulare a sa este T1. Am putea actualiza estimarea noastra printr-o suma a acestor doua valori, adica aT0+(1-a)T1. Odata cu alegerea lui a putem sa decidem daca dorim ca procesul de estimare sa uite vechile rulari sau daca dorim sa le tina minte mult timp. Daca a=1/2, obtinem estimari succesive dupa cum urmeaza: T0, T0/2+T1/2, T0/4+T1/4+T2/2, T0/8+T1/8+T2/4+T3/2 Dupa trei noi rulari, valoarea lui T0 in noua estimare a scazut la 1/8.Tehnica estimarii valorii urmatoare intr-o serie prin luarea mediei valorii curente masurate impreuna cu estimarea anterioara se mai numeste si "imbatranire". Se poate aplica in multe situatii in care este necesara o estimare bazata pe valorile anterioare. "Imbatranirea este usor de implementat mai ales cand a=1/2. Singurul lucru care trebuie facut este adaugarea noii valori la estimarea curenta si impartirea sumei la 2. Merita sa subliniem ca algoritmul "intai cea mai scurta sarcina" este potrivit doar atunci cand sarcinile trebuie efectuate simultan. Un contra-exemplu in acest sens: exista cinci sarcini, de la A la E, cu timpuri de rulare de 2,4,1,1 si respectiv 1. Timpurile lor de sosire sunt 0,0,3,3 si 3. Initial, doar A si B pot fi alese deoarece celelalte inca nu au ajuns. Utilizand algoritmul in care cea mai scurta sarcina are prioritate vom rula sarcinile in ordinea A,B,C,D si E si vom avea o medie de asteptare de 4.6. Totusi, rulandu-le in ordinea B,C,D,E,A vom avea o medie de asteptare de 4.4.

E. Administrarea garantata
O abordare complet diferita a temporizarii o constituie promisiunile realiste facute utilizatorului in ceea ce priveste performanta si apoi indeplinirea lor. O promisiune 63

Aritoni Ovidiu

Sisteme de operare 1

realista si usor de realizat este aceasta: daca exista n utilizatori conectati in momentul in care lucrati dvs., veti beneficia de aproximativ 1/n din capacitatea procesorului. La fel intr-un sistem cu un singur utilizator care are n procese ruland, toate avand aceeasi importanta, fiecare ar trebui sa primeasca 1/n din ciclurile procesorului. Pentru a tine aceasta promisiune, sistemul trebuie sa tina o evidenta in ceea ce priveste timpul alocat de procesor fiacarui proces inca de la initierea acestuia. Apoi calculeaza cantitatea de procesor la care fiecare proces are dreptul, adica timpul scurs de la initierea sa impartit la n. De vreme ce timpul alocat de catre procesor fiecarui proces este deja cunoscut este usor de calculat raportul dintre cantitatea de procesor avuta si cea la care are dreptul. Un raport de 0.5 inseamna ca procesul a avut doar jumatate din timpul la care avea dreptul, iar un raport de 2.0 arata ca procesul a folosit de doua ori mai mult timp decat avea alocat. In acest caz algoritmul spune sa se ruleze procesul cu cel mai mic raport pana cand acest raport este mai mare decat al celui mai apropiat competitor.

F. Administrarea aleatorie
Desi promisiunile facute utiliziatorilor si indeplinirea lor este o idee buna, ea este greu de implementat. Totusi, un alt algoritm poate fi utilizat; acesta are rezultate aproape la fel de previzibile si este foarte usor de implementat. Aceasta este temporizarea aleatorie (Waldspurger si Weihl, 1994). Ideea de baza este acordarea de bilete de loterie proceselor, pentru diferite resurse ale sistemului, cum ar fi timpul de utilizare a procesorului. De fiecare data cand trebuie luata o decizie de temporizare este ales la intamplare un bilet de loterie si procesul caruia i-a fost atribuit acel bilet primeste resursa respectiva. Cand acest lucru se aplica la temporizarea procesorului extragerea se poate face de 50 de ori pe secunda, fiecare castigator primind ca premiu 20 de msec. din timpul procesorului. Pentru a-l parafraza pe George Orwell: "Toate procesele sunt egale, dar unele sunt mai egale." Proceselor mai importante le pot fi atribuite bilete suplimentare pentru a le mari sansele de castig. Daca exista 100 de bilete restante si un proces detine 20 dintre ele, acesta va avea sanse de 20% sa castige fiecare extragere. Pe termen lung, va obtine 20% din timpul procesorului. Spre deosebire de un temporizator prioritar unde este foarte greu de stabilit ce inseamna exact o prioritae de 40, aici regula este clara: un proces care detine o fractiune f din totalitatea biletelor va obtine o fractiune f din totalitatea resurselor in chestiune. Temporizarea aleatorie are cateva proprietati interesante. De exemplu, daca apare un nou proces si ii sunt acordate cateva bilete, la urmatoarea extragere sansele de castig vor fi direct proportionale cu numarul de bilete pe care le detine. Cu alte cuvinte, temporizarea aleatorie este foarte darnica. Daca se doreste se pot schimba bilete intre procese cooperante. De exemplu daca un proces-client trimite un mesaj unui proces-server si apoi se blocheaza poate sa cedeze toate biletele serverului pentru a creste sansele serverului de a castiga runda urmatoare. Cand serverul a terminat inapoiaza biletele, astfel incat clientul sa poata rula din nou. De fapt, in absenta clientilor serverele nici nu au nevoie de bilete. Temporizarea aleatorie poate fi folosita pentru a trata probleme mai greu de rezolvat prin alte metode. Un exemplu este un server video in care mai multe procese 64

Aritoni Ovidiu

Sisteme de operare 1

trimit fluxuri video clientilor lor, dar la rate diferite de frame-uri. Sa presupunem ca procesele au nevoie de frame-uri la o rata de 10, 20 si 25 frame-uri/sec. Alocand acestor procese 10, 20 si respectiv 25 de bilete timpul procesorului va fi impartit automat in mod corespunzator.

G. Administrara in timp real


Un sistem in timp real este unul in care timpul joaca un rol esential. In general, unul sau mai multe dispozitive fizice, externe computerului genereaza stimuli la care computerul trebuie sa reactioneze corespunzator intr-un interval de timp bine stabilit. De exemplu, computerul dintr-un compact disc player primeste bitii si trebuie sa-i converteasca in muzica intr-un interval de timp foarte scurt. Daca este depasit acest interval, muzica va suna ciudat. Alte sisteme in timp real sunt monitorizarea pacientilor din sectiunea de tratament intensiv a unui spital, pilotul automat al unui aparat de zbor si controlul de siguranta dintr-un reactor nuclear. In toate aceste cazuri, obtinerea unui raspuns bun dar prea tarziu este adesea la fel de grav ca si cum nu l-am fi primit deloc. Sistemele in timp real sunt in general impartite in "timp real dur", insemnand ca exista termene limita care trebuie neaparat respectate si "timp real bland", ceea ce inseamna ca se poate tolera o nerespectare a termenului impus. In ambele cazuri comportamentul de timp real se realizeaza prin divizarea programului intr-un numar de procese al caror comportament este previzibil si stiut dinainte. Aceste procese sunt in general scurte si pot fi duse la capat in mai putin de o secunda. Cand un eveniment extern este detectat, temporizatorul este cel care trebuie sa temporizeze astfel procesele incat termenul limita sa fie respectat. Evenimentele carora trebuie sa le raspunda sistemele in timp real pot fi impartite in periodice (cele care apar la intervale regulate) si aperiodice (cele a caror aparitie nu poate fi prevazuta). Se poate ca un sistem sa trebuiasca sa raspunda mai multor fluxuri de evenimente periodice. Este posibil sa nu se poata raspunde tuturor, acest lucru depinzand de timpul de care ficare eveniment are nevoie pentru procesare. De exemplu, daca exista m evenimente periodice, iar evenimentul i apare cu o frecventa Pi si necesita Ci secunde din timpul procesorului pentru a trata fiecare eveniment, atunci incarcarea poate fi facuta doar daca FORMULA Daca un sistem in timp real poate sa indeplineasca acest criteriu inseamna ca acel sistem poate fi temporizat. De exemplu, ganditi-va la un sistem "timp real bland" cu trei evenimente periodice cu perioade de 100, 200 respectiv 500 msec. Daca aceste evenimente necesita 50, 30 respectiv 100 msec. din timpul procesorului pentru fiecare eveniment, inseamna ca sistemul este temporizabil deoarece 0.5+0.15+0.2<1. Daca este adaugat un al patrulea eveniment cu o perioada de 1 secunda, sistemul va ramane temporizabil atata vreme cat acest ultim eveniment nu necesita mai mult de 150 msec. din timpul procesorului pentru fiecare eveniment. In acest calcul se presupune ca schimbarea de context se face intr-un interval atat de scurt incat poate fi ignorat. Algoritmii de temporizare in timp real pot fi dinamici sau statici. Primii iau deciziile de temporizare in timpul rularii; cei din urma iau aceste decizii inainte ca 65

Aritoni Ovidiu

Sisteme de operare 1

sistemul sa inceapa sa ruleze. Haideti sa vedem pe scurt cativa algoritmi dinamici de temporizare in timp real. Algoritmul clasic este "algoritmul cu rata monotona" (Liu si Layland, 1973). Acest algoritm atribuie dinainte fiecarui proces o prioritate proportionala cu frecventa cu care apare evenimentul sau de tragere. De exemplu, un eveniment care trebuie sa ruleze la fiecare 20 msec. primeste prioritate 50, iar un proces care trebuie sa ruleze o data la 100 msec. primeste prioritate 10. Atunci cand procesul cu cea mai mare prioritate este pregatit sa ruleze, temporizatorul il ruleaza tot timpul pe acesta, chiar daca trebuie sa intrerupa alt proces care inca ruleaza in momentul respectiv. Liu si Layland au dovedit ca acest altgoritm este fiabil. Un alt algoritm de temporizare reala foarte des intalnit este "intai primul termen limita" De fiecare data cand este detectat un eveniment, procesul sau este adaugat pe lista proceselor pregatite pentru a fi rulate. Lista se tine aranjata in functie de termenul limita, care pentru un eveniment periodic inseamna urmatoarea aparitie a sa. Algoritmul va rula primul proces de pe lista, cel care are termenul limita cel mai apropiat. Un al treilea algoritm calculeaza cantitatea de timp pe care o are in plus fiecare proces, adica neglijenta sa. Daca un proces are nevoie de 200 msec. pentru a se finaliza si trebuie sa fie terminat in 250 msec., inseamna ca neglijenta sa este de 50 msec. Algoritmul, numit si "cea mai mica neglijenta" alege procesul cu cel mai putin timp in plus. Desi teoretic este posibil sa transformam un sistem de operare general intr-un sistem in timp real prin utilizarea unuia dintre acesti algoritmi de programare, in practica, in sistemele generale schimbarea de context dureaza atat de mult incat performanta unui sistem in timp real poate fi atinsa doar pentru aplicatiile cu termene limita destul de mari. In consecinta, pentru majoritatea lucrarilor in timp real se utilizeaza sisteme speciale pentru operare in timp real, care au anumite proprietati foarte importante. De obicei printre acestea se numara o marime mica, timp de intrerupere foarte scurt, schimbarea rapida a contextelor, un interval foarte scurt in care intreruperile nu functioneaza si posibilitatea de administrare a mai multor cronometre la intervale de milisecunde sau microsecunde.

H. Administrarea pe doua nivele


Pana acum am presupus mai mult sau mai putin ca toate procesele care pot fi rulate exista in memoria principala. Daca nu exista suficienta memorie principala disponibila, unele dintre procesele care pot fi rulate vor trebui depozitate pe disk, in intregime sau doar o parte din ele. Aceasta situatie are implicatii majore pentru temporizare deoarece timpul de schimbare a unui proces si incarcarea altuia de pe disk implica mai mult o ordine a importantei decat schimbarea cu un proces deja existent in memoria principala. Un mod mai practic de tratare a proceselor scoase din memorie este utilizarea unui temporizator pe doua nivele. Intai, doar parti ale proceselor care pot fi rulate sunt incarcate in memoria principala, asa cum se vede in figura 2-25(a). Apoi, pentru un timp temporizatorul se limiteaza la alegerea proceselor doar din aceste parti existente in memoria principala. Din cand in cand,un temporizator de nivel superior este solicitat sa stearga din memorie acele procese care exista acolo de mai mult timp si sa incarce acele procese care sunt de mult timp pe disk. Odata schimbarea efectuata, ca in figura 2-25(b) temporizatorul de nivel inferior se limiteaza din nou la alegerea proceselor dintre cele 66

Aritoni Ovidiu

Sisteme de operare 1

existente in memorie. Astfel, temporizatorul de nivel inferior este cel care alege dintre procesele care pot fi rulate existente in memorie, iar temporizatorul de nivel superior este cel care se ocupa cu transferul proceselor in ambele sensuri intre disk si memoria principala.

Fig. 2-25. Un temporizator pe doua nivele trebuie sa mute procesele intre disk si memoria principala, precum si sa aleaga dintre procesele existente in memorie pe cele care vor rula. (a), (b) si (c) reprezinta trei momente diferite. Un temporizator de nivel superior tine cont de mai multe criterii atunci cand ia deciziile. Dintre acestea amintim urmatoarele: 1. Cat timp a trecut de cand procesul a fost introdus sau scos din memorie? 2. Cat timp a beneficiat de procesor in ultima perioada? 3. Cat de lung este procesul? (Cele mici nu incurca) 4. Cat de ridicata este prioritatea procesului? Si in acest caz putem folosi algoritmul circular sau cel prioritar sau orice alta metoda. Nu este obligatoriu ca cele doua temporizatoare sa foloseasca acelasi altgoritm.

I. Politica versus mecanism


Pana acum am presupus ca toate procesele din sistem apartin unor utilizatori diferiti si prin urmare sunt in competitie pentru obtinerea procesorului. Desi acest lucru este valabil in majoritatea situatiilor se intampla si ca un proces sa aiba mai multe procese subordonate. De exemplu, un proces al unui sistem de administrare a unei baze de date poate avea mai multe procese subordonate. Se poate ca fiecare proces subordonat sa lucreze la o comanda diferita sau ca fiecare sa aiba o functie de indeplinit (analizarea unei probleme, accesul la disk, etc.). Este foarte posibil ca procesul principal sa considere ca unul dintre procesele secundare este mai important decat celelalte, iar altul mai putin important decat toate celelalte. Din pacate, nici unul dintre temporizatoarele analizate mai sus nu accepta implicarea proceselor utilizatoare in luarea deciziilor de temporizare. In consecinta, rareori se intampla ca temporizatorul sa ia cea mai buna decizie. 67

Aritoni Ovidiu

Sisteme de operare 1

O solutie la aceasta problema ar fi separarea mecanismului de temporizare de politica de temporizare. Acest lucru inseamna ca algoritmul de temporizare este parametrizat intr-un fel, dar parametrii pot fi stabiliti de catre procesele utilizatoare. Sa luam din nou exemplul cu baza de date. Sa presupunem ca kernelul utilizeaza un algoritm de temporizare prioritara dar furnizeaza un apel de sistem prin care un proces poate sa seteze (si sa schimbe) prioritatile proceselor subordonate lui. Astfel, fiecare proces principal poate sa controleze in detaliu modul in care sunt temporizate procesele subordonate lui, chiar daca nu este el cel care face temporizarea. In acest caz mecanismul se afla in kernel, dar politica este stabilita de un proces utilizator.

68

Aritoni Ovidiu

Sisteme de operare 1

3.Intrari/Iesiri

69

Aritoni Ovidiu

Sisteme de operare 1

1. Principiile hardware-ului I/O

Oamenii privesc hardware-ul I/O in moduri diferite. Electricienii vad cipuri, fire, sursa de curent, motoare si alte componente fizice care alcatuiesc hardware-ul. Programatorii vad interfata unui software comenzile pe care le accepta hardware-ul, functiile pe care le indeplineste si afisarea erorilor. In aceasta carte ne ocupam de programarea dispozitivelor I/O, nu de proiectarea, construirea sau mentinerea lor; deci suntem interesati doar de modul in care este programat hardware-ul , nu de modul in care functioneaza in interior. Totusi programarea multor dispozitive I/O este adesea strans legata de operatiile din interiorul lor. In urmatoarele trei sectiuni va vom furniza cateva informatii generale despre modul in care hardware-ul I/O relationeaza cu programarea.

A.Dispozitivele I/O
Aceste dispozitive pot fi impartite in doua categorii principale: dispozitive in bloc si dispozitive de caracter. Un dispozitiv in bloc este cel care depoziteaza informattile in blocuri de marime fixa, fiecare bloc avand adresa proprie. Marimea unui bloc variaza de la 512 biti pana la 32.768 biti. Calitatea principala a unui astfel de dispozitiv este capacitatea sa de a citi sau scrie fiecare bloc independent de toate celelalte. Disk-urile sunt cele mai cunoscute dispozitive in bloc. La o analiza mai atenta ne dam seama ca limita dintre dispozitivele care au blocuri carora ne putem adresa si cele care nu au asa ceva nu este bine definita. Toata lumea este de accord ca disk-ul este un dispozitiv de adresare in bloc deoarece indiferent unde se afla bratul in momentul respectiv, el poate sa caute pe alt cilindru si apoi sa astepte ca blocul dorit sa ajunga sub capul de citire. Sa ne gandim la o banda de 8 mm sau DAT utilizata pentru a realiza backup-urile disk-ului. In general aceste benzi contin blocuri de marime fixa. Daca driver-ului benzii ii este data comanda sa citeasca blocul N, poate sa deruleze banda inainte pana ajunge la blocul N. Aceasta operatiune este similara cu cautarea facuta de disk, dar dureaza mult mai mult timp. De asemenea, nu este sigur ca un bloc se poate rescrie in mijlocul benzii. Chiar daca ar fi fost posibil sa folosim benzile ca dispozitive in bloc cu accesare aleatorie, acest lucru ar fi un pic fortat : in mod normal nu sunt folosite astfel. Celalalt tip de dispozitiv este dispozitivul de caracter. Un astfel de dispozitiv furnizeaza sau accepta un flux de caractere, fara sa tina cont de vreo structura in bloc. Nu poate fi contactat si nu are operatiune de cautare. Printere, interfete de retea, mouse (pentru indicare), sobolani (pentru experimente de psihologie in laborator), precum si multe alte dispozitive care nu intra in categoria disk-ului pot fi privite ca dispozitive de caracter. Aceasta schema de clasificare nu este perfecta. Unele dispozitve nu intra in nici una din aceste doua categorii. Ceasurile de exemplu, nu au blocuri care pot fi contactate si nici nu genereaza sau accepta fluxuri de caractere. Singurul lucru pe care il fac este sa produca intreruperi la intervale de timp bine stabilite. Nici ecranele cu scheme de 70

Aritoni Ovidiu

Sisteme de operare 1

memorie nu se incadreaza prea bine in acest model. Totusi, acest model este destul de general incat poate fi folosit ca baza pentru a face ca intr-un sistem de operare softwareul care lucreaza cu dispozitivele I/O sa fie independent. Sistemul de fisiere de exemplu, lucreaza doar cu dispozitive abstracte in bloc si lasa partea dependenta de dispozitiv in seama software-ului de nivel scazut numit si drivere pentru dispozitiv.

B. Controllere de dispozitiv

De obicei, unitatile I/O includ o componenta mecanica si una electronica. Adesea cele doua componente se pot separa pentru a le conferi un design mai modular si mai general. Componenta electronica se numeste controller de dispozitiv sau adaptor. Pe computerele personale ia adesea forma unei placi cu circuit imprimat si care poate fi introdusa intr-unul din slot-urile existente pe placa de baza. Componenta mecanica o constituie chiar dispozitivul. Placa de control este de obicei prevazuta cu un conector in care poate fi introdus un cablu care sa faca legatura direct cu dispozitivul. Multe controllere pot sa sustina doua, patru sau chiar opt dispozitive identice. Daca interfata dintre controller si dispozitiv este una standard sau una oficiala asa cum sunt ANSI, IEEE sau ISO sau una inclusa de producator, atunci companiile pot sa realizeze controllere sau dispozitive care sa fie compatibile cu interfata respectiva. De exemplu, multe companii proiecteaza disk drivere care sa fie compatibile cu interfetele de disk controller IDE sau SCSI. Precizam aceasta diferenta intre controller si dispozitiv deoarece sistemul de operare lucreaza aproape intotdeauna cu controllerul si nu cu dispozitivul. Cele mai multe computere mici utilizeaza doar modelul de bus din figura 3-1 pentru comunicarea dintre procesor si controllere. Frame-urile principale mari folosesc adesea un model diferit, cu mai multe bus-uri si computere specializate pe I/O numite canale I/O care preiau o parte din sarcinile procesorului principal.

Fig. 3-1 Un model de conectare a procesorului, memoriei, controllerelor si dispozitivelor I/O. Interfata dintre controller si dispozitiv este adesea o interfata de nivel scazut. Un disk de exemplu, poate fi formatat cu 16 sectoare a cate 512 bytes pe fiecare pista . Ceea 71

Aritoni Ovidiu

Sisteme de operare 1

ce vine efectiv de pe drive este un flux de biti in serie incepand cu un preambul, apoi cei 4096 de biti dintr-un sector si, in final, suma de verificare numita si cod de corectare a erorilor (ECC). Preambulul se scrie atunci cand este formatat disk-ul si contine numarul de cilindru si cel de sector, marimea sectorului si alte date asemanatoare precum si informatiile de sincronizare. Sarcina controller-ului este sa converteasca fluxul serial de biti intr-un bloc de bytes si sa corecteze erorile aparute. De obicei blocul de bytes este initial asamblat bit cu bit intr-un buffer (zona tampon) din interiorul controller-ului. Dupa ce a fost verificat si declarat fara erori poate fi copiat in memoria principala. Controller-ul pentru un terminal CRT functioneaza tot ca un dispozitiv cu biti in serie si tot la nivel scazut. Acesta citeste bitii existenti in memorie si care contin caractere de afisat si genereaza semnale utilizate pentru modularea fascicolului CRT pentru ca acesta sa scrie pe ecran. Tot controller-ul este cel care genereaza semnale care determina fascicolul CRT sa se retraga orizontal dupa ce a terminat o linie de scanare si o retragere verticala dupa ce intregul ecran a fost scanat. Daca nu ar fi existat controller-ul CRT programatorul sistemului de operare ar fi trebuit sa programeze explicit scanarea analoaga a tubului. Astfel, sistemul de operare ii furnizeaza controller-ului cativa parametrii cum ar fi numarul de caractere per linie si numarul de linii per ecran, si lasa controller-ul sa conduca efectiv fascicolul. Fiecare controller are cativa registri care sunt utilizati pentru comunicarea cu procesorul. Pe unele computere acesti registri sunt integrati in spatiul alocat adresei memoriei. Aceasta schema se numeste schema de memorie I/O. 6800 de exemplu, utilizeaza aceasta metoda. Alte computere folosesc spatiu special pentru adresa I/O, fiecare controller avand alocata o portiune din acest spatiu. Repartizarea adresei I/O dispozitivelor se face de catre logica decodarii bus-urilor asociata cu controller-ul. Unii producatori de asa numitul PC IBM compatibil folosesc adrese I/O diferite de cele folosite de IBM. In plus fata de porturile I/O, multe controlere folosesc intreruperi pentru a-I comunica procesorului momentul in care sunt pregatite scrierea sau citirea registrilor. O intrerupere este in primul rand un eveniment electric. O Cerere de Intrerupere a liniei este o intrare fizica in cipul de intrerupere al controll-erului. Numarul unor astfel de intrari este limitat; PC din clasa Pentium au doar 15 dispozitive disponibile pentru I/O. Unele controller-e sunt conectate pe placa de baza prin disopzitive hard ca la IBM PC. In cazul unui controller care se conecteaza in partea din spate, comutatoarele sau jumper dispozitivului controller-ului pot fi folositi, cate odata pentru a selecta IRQ pe care-l va folosi dispozitivul pentru a evita conflictele (desi in cazul unor placi plugn play IRQ poate fi setat din software). Cipul controller-ului de intreruperi monitorizeaza fiecare intrare IRQ la vector de intrerupere care localizeaza software-ul corespunzator de intrerupere a sarcinii. Figura 3-2 arata adresele I/O, intreruperile de hardware si vectorii de intrerupere alocati unor controlere de pe un IBM PC de exemplu. MINIX utilizeaza aceleasi intreruperi hardware, dar vectorii de intrupere MINIX sunt diferiti de cei aratati aici pentru ms-dos. Sistemul de operare executa I/O scriind comenzi in registrii controller-ului. Controller-ul floppy-disk-ului IBM PC de exemplu accepta 15 comenzi diferite, cum sunt: CITESTE, SCRIE, CAUTA, FORMATEAZA si RECALIBREAZA. Multe dintre comenzi au parametrii, care sunt de asemenea incarcati in registrii controller-ului. Atunci cand o comanda a fost acceptata procesorul poate sa lase controller-ul sincur si sa inceapa alta sarcina. Atunci cand comanda a fost executat, controller-ul executa o intrerupere pentru a permite sistemului de operare sa preia controlul asupra procesorului si sa testeze 72

Aritoni Ovidiu

Sisteme de operare 1

rezultatele operatiei. Procesorul obtine rezultatele si statulul dispozitivului citind unul sau mai multi bytes de informatie din registrii controller-ului.

fig 3-2.cateva exemple de controller-e, adresele lor I/O, liniile de intrerupere hardware si vectorii lor de intrerupere pe un PC obisnuit care ruleaza in MSDOS

C. Aces direct la memorie (DMA)


Multe controller-e mai ales cele utilizate pentru dispazitive in bloc suporta Acces direct la memorie sau DMA. Pentru a explica cum functioneaza DMA sa ne uitam mai intai la modul cum apar citirile de disk atunci cand DMA nu este utilizat. Mai intai controller-ul citeste in serie blocul (unul sau mai multe sectoare) de pe drive bit cu bit pana cand intregul bloc sa afla in buffer-ul intern al controller-ului. Apoi, acesta calculeaza suma de verificare pentru a vedea daca au aparut erori de citire. Apoi controller-ul produce o intrerupere. Cand sistemul de operare incepe sa ruleze poate sa citeasca blocul disk-ului de pe buffer-ul controller-ului cate un byte sau cate un cuvant odata executand un loop, prin fiecare iteratie citind un byte sau un cuvant din registrul dispozitivului controller-ului pe care il depoziteaza in memorie. Fireste, un loop al procesorului programat sa citeasca bytes unul cate unul de pe controller iroseste timpul procesorului. DMA a fost inventat pentru a elibera procesorul de aceasta munca de nivel scazut. Atunci cand este utilizat, procesorul da controller-ului 2 informatii pe langa adresa de disk a blocului: adresa de memorie a depozitarii blockului si numarul de bytes care trebuie transferati asa cum se vede in figura 3-3.

73

Aritoni Ovidiu

Sisteme de operare 1

fig3-3. Un transfer DMA se face in intregime de controller Dupa ce controller-ul a citit in intregime blocul de pe dispozitiv in buffer-ul sau si a verificat suma copiaza primul byte sau cuvant in memoria principala la adresa specificata de memoria de adresa DMA. Apoi incrementeaza adresa DMA si decrementeaza contul DMA in functie de numarul de biti care tocmai au fost transferati. Acest proces se repeta pana cand contul DMA ajunge la 0, moment in care controller-ul produce o intrerupere. Cand sistemul de operare porneste nu mai trebuie sa copieze blocul in memorie; acesta este deja acolo. Poate va intrebati de ce controller-ul nu depoziteaza bytes in memoria principala imediat ce-I ia de pe disk. Cu alte cuvinte de ce are nevoie de un buffer intern? Motivul este ca odata cu inceperea unui transfer de pe disk, bits contiua sa soseseasca de pe disk cu o rata constanta indiferend daca controller-ul este sau nu pregatit pentru acest lucru controller-ului. In cazul in care controller-ul ar incerca sa scrie date direct in memorie ar trebui sa treaca peste buss-ul sistemului pentru fiecare cuvant transferat. Daca buss-ul ar fi ocupat din cauza utilizarii lui de catre alt dispozitiv controller-ul ar trebui sa astepte. Daca urmatorul cuvant ar sosi inainte ca precedentul sa si fost depozitat controller-ul ar trebui sa-l depoziteze undeva. Daca buss-ul ar fi foarte ocupat controller-ul ar putea sfarsi depozitand destul de multe cuvinte si avand de facut destul de multa munca de administrare. Cand blocul este amortizat in interior nu este nevoie de buss pana la pornirea DMA-ului, deci designul controller-ului este mult mai simplu din cauza transferului facut de DMA in memorie, nu este presat de timp. (De fapt unele controlere mai vechi mergeau direct la memorie doar cu o mica amortizare interna, dar cand buss-ul era foarte ocupat, se putea intampla ca un transfer sa se incheie cu o eroare cauzata de suprasolicitare.) Procesul de amortizare in doi timpi descris mai sus are implicatii majore pentru performanta I/O. in timp ce datele sunt transferate din controller in memorie fie de catre procesor fie de catre controller, sectorul urmator va trece pe sub capul de citire al discului iar bits vor ajunge in controller. Controller-ele simple nu pot face fata executarii intrarilor si iesirilor in acelasi timp, astfel ca in timp ce are loc un transfer de memorie, sectorul care trece pe sub capul de citire al discului este pierdut.

74

Aritoni Ovidiu

Sisteme de operare 1

In consecinta controller-ul va putea sa citeasca doar cate un bloc. Citirea unei piste complete va necesita doua rotatii complete, una pentru blocurile pare si una pentru impare. Daca timpul de transfer al unui bloc din controller in memorie prin buss este mai lung decat timpul de citire al unui bloc de pe disk ar putea fi necesara citirea unui bloc si sarirea a altor doua (sau mai multe) blocuri. Sarirea peste unele blocuri pentru a-I da timp controller-ului sa transfere datele in memorie sa numeste inserare. Cand disk-ul este formatat blocurile sunt astfel numerotate incat sa tina evidenta factorului de inserare. In figura 3-4(A) vedem un disk cu 8 blocuri/pista si fara inserare. In figura 3-4(B) vedem acelasi disk cu o singura inserare. In figura 3-4(C) se vede o dubla inserare.

Fig 3-4. (a) fara inserare. (b) o singura inserare. (c) dubla inserare Pentru acest mod de numerotare a blocurilor, ideea este sa permita sistemului de operare sa citeasca consecutiv blocurile numerotate si sa atinga, si in acest caz viteza maxima de care este capabil hardware-ul. Daca blocurile ar fi numerotate ca in figura 3-3(A) dar controller-ul ar putea citi doar blocurile alternative, un sistem de operare care ar aloca unui fisier opt blocuri de disk consecutive ar necesita 8 rotatii de disk pentru a citi in ordine blocurile de la 0 la 7 (bine-nteles daca sistemul de operare ar cunoaste problema si ar distribui altfel blocurile ar putea sa rezolve problema din software, dar este mai bine sa se ocupe controller-ul de inserare). Nu toate computerele folosesc DMA. Principalul argument contra este acela ca procesorul principal este adesea mult mai rapid decat controller-ul DMA si poate indeplini sarcina mai rapid (cand factorul limitativ nu este dispozitivul I/O). In lipsa altei sarcini nu are rost ca rapidului procesor sa astepte dupa terminarea incetului controller DMA. De asemenea debarasarea de controller-ul DMA si folosirea procesorului pentru software economiseste bani.

2. Principii ale software-ului I/O


Sa lasam hardware-ul deoparte si sa analizam modul de structurare al softwareului I/O. Scopurile generale ale software-ului I/O sunt usor de stabilit. Ideea principala este organizarea software-ului sub forma de straturi, unde cele de jos sunt folosite pentru 75

Aritoni Ovidiu

Sisteme de operare 1

ascunderea particularitatilor de cele de sus. Iar cele de sus trebuie sa prezinte utilizatorilor o interfata draguta curata si uniforma. In sectiunile urmatoare vom analiza aceste scopuri si modul in care ele sunt realizate.

A.Scopurile software-ului I/O


Un concept cheie proiectarea software-ului I/O este cunoscut ca independenta dispozitivului. Acest lucru inseamna ca ar trebui sa se poata scrie programe care sa poata citi fisiere de pe un floppy disk, hard disk sau cd-rom fara a fi nevoie sa se modifice programul pentru fiecare tip diferit de dispozitiv. Ar trebui sa se poata tasta o comanda cum ar fi sort <inpu> output care sa functioneze cu intrare de pe floppy disk, hard disk sau tastatura si rezulatul sa mearga la floppy disk, hard disk sau chiar la monitor. Sistemul de operare este cel care trebuie sa rezolve problemele cauzate de faptul ca aceste dispozitive chiar sund diferite si necesita diferite driver-e de dispozitiv pentru a scrie datele pe dispozitive de afisare a rezultatului. Strans legat de independenta dispozitivului este scopul de numirea uniforma. Numele unui fisier sau al unui dispozitiv ar trebui sa fie pur si simplu cuvant sau un tot si sa nu depinda de dispozitiv in nici un fel. In UNIX toate discurile pot fi integrate impreuna in ierarhia sistemelor de fisiere in moduri arbitrare astfel incat utilizatorul nu are nevoie sa stie carui dispozitiv ii corespunde un nume. De exemplu un floppy disk poate fi urcat in varful dosarului /usr/ast/backup astfel ca daca copiem un fisier in usr/ast/backup/Monday fisierul se va copia pe floppy disk. Astfel atat fisierelor cat si dispozitivelor ne adresam in acelasi mod: printr-un path name. Un alt punct important pentru software-ul I/O este tratarea erorilor. In general erorile ar trebui tratate pe cat posibil, in cat mai stransa legatura cu hardware-ul. In cazul in care controller-ul descopera o eroare de citire ar trebui sa incerce sa o corecteze daca poate. Daca nu poate, atunci driverul dispozitivului ar trebui sa o corecteze, probabil prin simpla incercare de a reciti blocul respectiv. Multe dintre erori sunt trecatoare, cum sun erorile de citire cauzate de fire de praf aparute pe capul de citire, si vor disparea odata cu repetarea operatiei. Straturile superioare trebuie informate de eroare doar daca straturile inferioare nu o pot remedia. In multe cazuri eroarea poate fi reparata in straturile de jos fara ca straturile superioare sa afle de eroarea respectiva. Totusi, un alt punct cheie il reprezinta transferurile sincronizate (blocate) versus cele nesincronizate (intrerupte). Cea mai mare parte dintre componentele fizice I/O sunt nesincronizate procesorul initiaza transferul si apoi continua cu alte sarcini pana in momentul intreruperii. Programele utilizatoare sunt mult mai usor de scris daca operatiile I/O se blocheaza-dupa ce a primit comanda citeste programul este automat suspendat pana cand datele sunt disponibile in buffer. Sistemul de operare este cel care trebuie sa faca in asa fel incat operatiile care sunt de fapt intrerupte sa para blocate pentru programele utilizatoare. Ultimul concept pe care-l vom trata aici il constituie dispozitivele comune versus dispozitivele dedicate. Unele dispozitive I/O cum sunt discurile pot fi folosite de mai multi utilizatori in acelasi timp. Faptul ca mai multi utilizatori au fisiere deschise de pe acelasi disk in acelasi timp nu cauzeaza probleme. Alte dispozitive cum sint driverele de 76

Aritoni Ovidiu

Sisteme de operare 1

banda trebuie sa fie dedicate unui singur utilizator pana cand acesta termina. Apoi alt utilizator poate beneficia de driverul de banda. In mod sigur nu se poate ca doi sau mai multi utilizatori sa scrie blocuri in acelasi timp si pe aceasi banda. Introducerea dispozitivelor dedicate (care nu pot fi impartite) produce si diferite probleme. Din nou sistemul de operare trebuie sa fie capabil sa lucreze ata cu dispozitivele dedicate cat si cu cele comune astfel incat sa evite problemele. Aceste scopuri pot fi realizate intr-un mod eficient prin sctucturarea software-ului I/O in patru straturi: 1.remedierea intreruperilor (cel mai jos) 2.driver-ele dispozitivului 3.software-ul sistemului de operare independent de dispozitiv 4.software la nivel de utilizator (cel mai sus) Aceste patru straturi sunt (nu intamplator) aceleasi patru straturi pe care le-am vazut in fig.2-26. in sectiunile urmatoare le vom analiza pe fiecare pe rand, incepand cu cel mai de jos. In acest capitol accentul se pune pe drive-ele de dispozitiv (stratul 2), dar vom rezuma si restul software-ului I/O pentru a arata modul in care conlucreaza diferitele componente ale sistemului I/O.

B.Remedierea intreruperilor
Intreruperile sunt o realitate neplacuta. Acestea ar trebui ascunse cat mai adanc in centrul sistemului de operare, asfel incat o cat mai mica parte a sistemului sa stie de ele. Cel mai bun mod de a le ascunde este de a face sa se blocheze fiecare proces care a inceput o operatie I/O, pana in momentul intreruperii cand I/O a incheiat. Procesul se poate bloca daca executa una din comenzile JOS la bariera, ASTEAPTA la o variabila de conditie sau PRIMESTE la un mesaj, de exemplu. Atunci cand are loc intreruperea procedura de intrerupere face tot ce este necesar pentru a debloca procesul care a initiat-o. La unele sisteme prin comanda SUS la o bariera. La altele un SEMNAL la o variabila de conditie din monitor, iar la altele se va trimite un mesaj procesului blocat. In toate cazurile efectul de retea va fi ca un proces pana acum blocat acum va putea rula.

C. Driver-e de dispozitiv
Toate codurile dependente de dispozitiv sunt trimise la driver-ele de dispozitiv. Fiecare driver de dispozitiv trateaza un tip de dispozitiv sau, cel mult, o clasa de dispozitive asemanatoare. De exemplu, ar fi probabil o idee buna sa existe un singur driver de terminal chiar daca sistemul suporta mai multe tipuri de terminaluri, putin 77

Aritoni Ovidiu

Sisteme de operare 1

diferite intre ele. Pe de alta parte, un terminal prost, o copie hard mecanica si un terminal inteligent cu grafica pe schema de biti si un mouse sunt atat de diferite incat se impune folosirea unor driver-e diferite. Pana acum in acest capitol am analizat functia controller-elor de dispozitiv. Am vazut ca fiecare controller are unul sau mai multi registri de dispozitiv utilizati pentru a ii da comenzi. Driver-ele de dispozitiv emit aceste comenzi si verifica indeplinirea corecta a lor. Astfel, disk driver-ul este singura parte a sistemului de operare care stie cati registri cre controller-ul respectiv si pentru ce sunt folositi. Doar el stie despre sectoare, piste, cilindri, capuri de citire, miscarea bratului, factori de inserare, motor, momentul de asezare al capului de citire si alte mecanisme care fac ca disk-ul sa functioneze cum trebuie. In termeni generali sarcina unui driver de dispozitiv este de a accepta cererile abstracte venite de la software-ul independent de dispozitiv superior lui si sa aiba grija ca aceste cereri sa fie indeplinite. Una din cererile obisnuite este sa se blocheze n. daca driver-ul nu lucreaza in momentul in care soseste o cerere, incepe imediat sa execute sarcina. Totusi, daca deja este ocupat cu alta cerere va inscrie cererea pe o lista de asteptare cu cereri care trebuie tratate cat mai curand posibil. Primul pas in tratarea unei cereri I/O pentru disk de exemplu, este traducerea ei din termeni abstracti in termeni concreti. Pentru un disk driver acest lucru inseamna localizarea blocului pe disk, verificarea daca motorul ruleaza, daca bratul se afla pe cilindrul corespunzator si asa mai departe. Pe scurt, trebuie sa decida care operatii ale controller-ului sunt necesare si in ce sectiune. Odata ce a stabilit care comenzi trebuie transmise controller-ului incepe sa le emita inscriindu-le in registrii dispozitivului controller-ului. Unele controllere pot sa trateze doar cate o comanda. Alte controller-e pot sa accepte o lista de comenzi pe care le trateaza singure fara alt ajutor din partea sistemului de operare. Dupa ce comanda sau comenzile au fost emise se va aplica una din cele doua situatii. In multe cazuri driver-ul de dispozitiv trebuie sa astepte pana cand controller-ul ii da ceva de lucru, astfel ca se blocheaza pana in momentul in care se produce intreruperea care il deblocheaza. Totusi, in alte cazuri operatia se incheie fara intarzieri, astfel ca nu este nevoie ca driver-ul sa se blocheze. Un exemplu al acestei situatii este ca derularea ecranului pe unele terminale nu necesita decat scrierea catorva bytes in registrii controller-ului. Nu este nevoie de nici o miscare mecanica, astfel ca intreaga operatie poate fi incheiata in cateva microsecunde. In primul caz driver-ul blocat va fi repornit de intrerupere. In cel de-al doilea nu se va bloca deloc. In oricare din cele doua cazuri dupa ce operatia s-a incheiat trebuie verificata sa nu aiba erori. Daca totul este in regula, se poate ca driver-ul sa aiba date de transmis softare-ului independent de dispozitiv (ex. Un bloc tocmai a fost citit.). in cele din urma, returneaza unele informatii de statut pentru raportarea erorilor inapoi la apelant. Daca mai exista alte cereri pe lista una dintre ele poate fi acum selectata si initiata. Daca nu exista nici o sarcina pe lista de asteptare, driver-ul se blocheaza in asteptarea cererii urmatoare.

D. Software I/O independent de dispozitiv


Desi o parte din software-ul I/O este specific pentru un anumit tip de dispozitiv exista si o parte destul de mare care este independenta de dispozitiv. Limita exacta dintre 78

Aritoni Ovidiu

Sisteme de operare 1

driver-e si software-ul independent de dispozitiv o stabileste sistemul deoarece unele functii care ar putea fi indeplinite intr-un mod independent de dispozitiv ar putea fi indeplinite in driver-e din ratiuni de eficienta sau din alte motive. Functiile aratate in fig. 3-5 sunt de obicei indeplinite de software-ul independent de dispozitiv. In MINIX, majoritatea software-ului independent de dispozitiv face parte din sistemul de fisiere, in stratul 3 (fig. 2-26). Desi vom analiza sistemul de fisiere in Cap. 5, vom arunca o privire rapida asupra software-ului independent de dispozitiv, pentru a da o imagine a I/O si a vedea mai bine unde se incadreaza driver-ele.

Fig. 3-5. functii ale software-ului I/O independent de dispozitiv Functia de baza a software-ului independent de dispozitiv este de a indeplini functiile I/O commune tuturor dispozitivelor si sa furnizeze o interfata uniforma pentru software-ul la nivel de utilizator. O problema majora intr-un system de operare este modul in care sunt numite obiectele cum sunt fisierele si dispozitivele I/O. software-ul independent de dispozitiv are grija ca numele simbolice ale dispozitivelor sa fie indicate pe driver-ele corespunzatoare. In UNIX un nume de dispozitiv, cum ar fi /dev/tty00, specifica doar nodul I pentru un anume fisier, iar acest nod I contine numarul major de dispozitiv, care este utilizat pentru a localiza driver-ul corespunzator. Acest nod mai contine si numarul minor de dispozitiv si care este transmis driver-ului ca parametru ce specifica unitatea care trebuie scrisa sau citita. Protectia este foarte strans legata de denumire. Cum face sistemul pentru a impiedica folosirea dispozitivului de catre utilizatori care nu au acest drept? In sistemele de pe computerele personale nu exista deloc protectie. Orice process poate sa faca orice. In cele mai multe dintre sistemele principale accesarea dispozitivelor I/O de catre procesele utilizatoare este complet interzisa. In UNIX este utilizata o schema mai flexibila. Fisierele corespunzatoare dispozitivelor I/O sunt protejate de bitii rwx. Si atunci administratorul sistemului poate sa seteze permisiunea corespunzatoare pentru fiecare dispozitiv. Disk-urile diferite pot sa aiba marimi diferite de sectoare. Depinde de software-ul independent de dispozitiv sa ascunda acest lucru si sa furnizeze straturilor de sus o marime de bloc uniforma, de exemplu prin tratarea catorva sectoare ca unic bloc logic. 79

Aritoni Ovidiu

Sisteme de operare 1

Astfel, straturile de sus au de-a face doar cu dispozitive abstracte care folosesc toate aceeasi marime de bloc logica, independenta de marimea fizica de sector. La fel unele dispozitive de caracter isi trasmit datele byte cu byte (ex. modem-ul), in timp ce altele si le transmit in unitati mai mari (ex. interfetele de retea). Si aceste diferente trebuie ascunse. Si amortizarea este o problema, atat pentru dispozitivele in bloc cat si pentru cele cu caractere. Pentru dispozitivele in bloc, hardware-ul insista in general pe citirea si scrierea blocurilor intregi dintr-o data, dar procesele utilizatoare sunt libere sa citeasca si sa scrie in unitati arbitrare. Daca un process utilizator scrie o jumatate de bloc, in mod normal sistemul de operare va tine datele in interior pana cand sunt scrise si restul datelor, moment in care intregul bloc poate fi transferat pe disk. Pentru dispozitivele cu caractere, utilizatorii pot sa introduca date in sistem mai repede decat poate acesta sa le scoata si de aceea este necesara amortizarea. Intrarea e tastatura care ajunge mai repede decat este nevoie necesita, de asemenea, amortizare. In timp ce se creaza un fisier de date, noile blocuri de disk trebuie sa fie allocate fisierului. Pentru a realiza aceasta alocare, sistemul de operare are nevoie de o lista sau schema de biti ale blocurilor libere pe fiecare disk, dar algoritmul pentru localizarea unui bloc liber este independent de dispozitiv si poate fi facut pe un nivel superior driver-ului. Unele dispozitive cum sunt cd-rom recorder pot fi utilizate in orice moment dat pentru un singur process. Sistemul de operare este cel care trebuie sa analizeze cererile de utilizare a dispozitivului si sa le accepte sau respinga in functie de disponibilitatea dispozitivului. Un mod simplu de-a rezolva aceste cereri este sa ceara proceselor sa execute comenzi de deschidere direct pe fisierele speciale pentru dispozitive. Daca dispozitivul nu este disponibil, comanda de deschidere nu se va executa. Un astfel de dispozitiv dedicat va fi eliberat doar dupa inchiderea sa. Remedierea erorilor se face de catre driver-e. cele mai multe erori sunt strans legate de dispozitiv, astfel incat numai driver-ul stie ce trebuie facut (ex. incearca din nou, ignora, alarma). O eroare des intalnita este cauzata de un bloc de disk care a fost avariat si nu mai poate fi citit. Dupa ce driver-ul a incercat sa citeasca blocul respective de mai multe ori, renunta si informeaza software-ul independent de dispozitiv. De aici incolo este independent de dispozitiv modul in care eroarea va fi tratata. Daca eroarea a aparut in timpul citirii unui fisier utilizator poate fi suficienta transmiterea erorii inapoi catre apelant. Totusi daca a aparut in timpul citirii structurii unui system critic de date, asa cum este blocul care contine schema de biti care arata blocurile libere s-ar putea ca sistemul de operare sa nu aiba alta alternativa decat sa afiseze un mesaj de eroare si sa incheie.

E. Spatiul utilizatorului software-ului I/O


Desi cea mai mare parte a software-ului I/O se afla in interiorul sistemului de operare, o mica parte a lui este formata din biblioteci legate intre ele prin programe utilizatoare si chiar programe intregi ruland in afara kernel-ului. Apelarile sistemului, inclusive apelarile sistemului I/O sunt in moe normal facute prin functiile bibliotecii. Cand un procram C contine apelul Count=write(fd, buffer, nbytes); 80

Aritoni Ovidiu

Sisteme de operare 1

Functia write a bibliotecii va fi legata de program si continuta in programul binary present in memorie in timpul rularii. Colectarea tuturor acestor functii de biblioteca constituie in mod evident o parte a sistemului I/O. In timp ce aceste functii fac putin mai mult decat sa isi inscrie parametrii in locul corespunzator pentru apelarea sistemului, exista alte functii I/O care intr-adevar lucreaza. Formatarea intrarii si iesirii se face prin functii din biblioteca. Un exemplu din C este printf, care ia un format de sir de caractere si posibil cateva variabile ca intrare, construieste un sir de caractere ASCII, si apoi apeleaza comanda scrie pentru a vizualiza sirul. Un exemplu de functie asemanatoare pentru intare este scanf care citeste intrarea si o depoziteaza in variabilele descries intr-un format de siruri de caractere folosind aceeasi sintaxa ca printf. Biblioteca I/O standard contine un numar de functii care implica I/O si functioneaza ca parte a programelor utilizatoare. Nu tot software-ul I/O de la nivelul utilizatorului consta in functii de biblioteca. Alta categorie importanta este sistemul in spirala. Spiralarea este un mod de a trata dispozitivele I/O dedicate intr-un sistem de programare. Un dispozitiv in spirala obisnuit este imprimanta. Desi din punct de vedere tehnic ar fi mai usor sa I se permita oricarui process utilizator sa deschida fisierul special de caractere pentru imprimanta, sa presupunem ca un process l-ar deschide si timp de mai multe ore nu ar face nimic. Asta ar insemna ca nici alt proces n-ar mai putea printa nimic. In schimb se creeaza un proces special numit daemon si un director special numit director de spiralare. Pentru a printa un fisier, un proces genereaza mai intai intregul fisier care trebuie printat si il depoziteaza in directorul de spiralare. Daemonul hotareste care este singurul proces caruia I se permite sa utilizeze fisierul special al imprimantei pentru a printa fisierele din director. Prin protejarea fisierului special impotriva folosirii directe de catre utilizator este eliminata posibilitatea ca cineva sa-l tina deschis mai mult decata este necesar. Spiarlarea nu este folosita doar pentru imprimante. Se foloseste si in alte situatii. De exemplu transferul de fisiere printr-o retea foloseste adesea un daemon de retea. Pentru a trimite undeva un fisier, un utilizator il pune in disrectorul de spiralare pentru retea. Mai tarziu daemonul de retea il scoate si il transmite. Un caz particular de transmitere spiralata a unui fisier este sistemul de posta elecronica prin internet. Aceasta retea consta in milioane de aparate din toata lumea ce comunica folosind mai multe retele de computere. Pentru atrimite cuiva un mesaj se apeleaza un program cum este send, care accepta scrisoarea care trebuie trimisa si apoi o depoziteaza intr-un director de spiralare pentru a o transmite ulterior. Intregul sistem de mesaje ruleaza in afara sistemului de operare. Figura 3-6 rezuma sistemul I/O aratand toate straturile precum si functiile principale ale fiecarui strat. Incepand de jos straturile sunt: hardware-ul, cererile de intrerupere, drivere de dispozitiv, software independent de dispozitiv si in cele din urma procesele utilizatoare. Sagetile din figura 3-6 arata fluxul de control. Cand un program utilizator incearca sa citeasca un bloc dintr-un fisier, de exemplu, sistemul de operare este invocat pentru a duce apelul la sfarsit. Software-ul independent de dispozitiv verifica depozitul de blocuri, de exemplu. Daca blocul necesar nu este acolo acesta apeleaza driver-ul dispozitivului pentru a transmite cererea catre hardware. Apoi procesul este blocat pana operatia de pe disk sa incheiat. 81

Aritoni Ovidiu

Sisteme de operare 1

Cand discul a terminat hardware-ul produce o intrerupere. Cererea de intrerupere este rulata pentru a descoperi ce sa intamplat adica, care este dispozitivul care solicita atentia in acel moment. Apoi extrage statutul de pe dispozitiv si porneste procesul resident pentru a finaliza cererea I/O si lasa procesul utilizator sa continue.

Fig 3-6. straturile sistemului I/O si functiile principale ale fiecarui strat.

3. Impasuri

Sistemele computerelor sunt pline de resurse care pot fi folosite de un singur process odata. Printer exemplele obisnuite se numara ploterele cu pat plat cd-rom reader si cd-rom recorder, sisteme de back-up pe banda de 8mm DAT si sloturile din tabla de process a sistemului. Existenta a doua procese care scriu simultan pe printer duce la erori. Existenta a doua procese ce utilizeaza acelasi slot din tabla de procese va duce, probabil la eronarea sistemului. In consecinta toate sistemele de operare au capacitatea sa garanteze temporar unui proces acces exclusiv la anumite resurse. Pentru multe aplicatii un proces are nevoie de acces exclusiv la mai multe resurse nu doar la una singura. Ganditiva de exemplu la o companie de vanzari care se specializeaza in vanzarea unor harti demografice mari si detaliate ale SUA executate pe un plotter cu plat plat de 1m latime. Informatia demografica vine prin cd-rom si contine recensamantul si alte date. Sa presupunem ca procesul A cere unitatea de cd-rom si o obtine. Un moment mai tarziu procesul B cere pltter-ul si il obtine si el. Acum procesul A cere si el plotter-ul si se blocheaza asteptandu-l. in cele din urma procesul B cere cd-romul si se blocheaza si el. In acest moment ambele procese sunt blocate si vor ramane asa pentru totdeauna. Aceasta situatie se numeste impas. Nu este bine sa aveti impasuri in sistemul dumneavoastra. 82

Aritoni Ovidiu

Sisteme de operare 1

Impasurile pot aparea in multe alte situatii pe langa solocitarea dispozitivelor I/O dedicate. De exemplu intr-un sistem de baze de date un program poate fi nevoit sa blocheze mai multe inregistrari pe care ele le foloseste, pentru a evita conditile de competitie. Daca procesul A blocheaza inregistrarea R1 si procesul B blocheaza inregistrarea R2 si apoi fiecare proces incearca sa blocheze inregistrarea celuilalt avem de asemenea un impas. Astfel impasurile pot sa apara atat pentru resursele hardware cat si pentru software. In aceasta sectiune vom analiza mai atent impasurile pentru a vedea atat modul in care apar cat si modul in care pot fi prevenite sau evitate. Ca exemplu vom vorbi despre obtinerea dispozitivelor fizice cum sunt benzile, cd-rom si plotter, deoarece acestea sunt usor de vizializat dar principiile si algoritmii sunt valabili si pentru alte tipuri de impasuri.

A. Resurse
Impasurile pot aparea atunci cand proceselor le-a fost garantat acces exclusiv la fisiere dispozitive etc. Pntru a generaliza cat mai mult discutia despre impasuri ne vom referi la obiectele garantate ca resurse. O resursa poate fi un dispozitiv hardware (o banda) sau o informatie (o inregistrare blocata dintr-o baza de date). In mod normal un computer poate avea mai multe resurse diferite care pot fi obtinute. Pentru unele resurse pot fi disponibile mai multe exemplare identice asa cum este unitatea cu trei benzi. Cand sunt disponibile mai multe copii ale unei resurse oricare din ele poate fi folosita pentru a satisface orice cerere de resurse. Pe scurt numim resursa orice care poate fi folosit la un moment dat de un singur proces. Resursele sunt de doua feluri: preemptibila si nepreemptibila. O resursa preemptibila este una care poate fi luata procesului care o foloseste fara efecte secundare pentru acesta. Memoria este un exemplu in acest sens. Ganditi-va, de exemplu la un sistem cu memorie utilizabila de 512k, o imprimanta, si doua procese de 512k ambele dorind sa printeze ceva. Procesul A cere si primeste imprimanta, apoi incepe sa calculeze valorile care trebuie printate. Inainte ca el sa termine calculul ii expira quantum-ul si este schimbat. Acum ruleaza procesul B si incearca fara sa reuseasca, sa obtina imprimanta. Acum avem o potentiala situatie de impas deoarece A are imprimanta si B are memoria si nici unul nu poate sa mearga mai departe fara resursa detinuta de celalalt. Din fericire este posibil sa I se ia memoria procesului B prin schimbarea lui cu procesul A. acum A poate sa ruleze, sa printeze si apoi sa elibereze imprimanta; astfel nu apare nici un impas. O resursa nonpreemptibila este una care nu ii poate fi luata utilizatorului ei curent fara a produce o esuarea a procesului. Daca un proces a inceput sa printeze rezultatul si ii luam imprimanta si o dam altui proces rezulatul va fi deformat. Imprimantele nu sunt preemptibile. In general impasurile implica resurse nonpreemptibile. Impasurile potentiale care implica resurse preemptibile pot fi rezolvate prin realocarea resursei de la un proces la altul. Astfel analiza noastra se va concentra asupra resurselor nonpreemptibile. Succesiunea evenimentelor, necesara pentru a folosi o resursa este 1 solicitarea resursei 2 utilizarea resursei 3 eliberarea resursei 83

Aritoni Ovidiu

Sisteme de operare 1

Daca resursa nu este disponibila in momentul solicitarii procesul de solicitare este nevoit sa astepte. La unele sisteme de operare procesul este blocat automat in momentul in care o solicitare de resurse esueaza si este repornit in momentul in care este disponibila. La alte sisteme solicitarea esueaza cu un cod de eroare, si procesul apelant trebuie sa astepte un timp si apoi sa reancerce.

B. Principii ale impasului

Impasul poate fi definit astfel: O serie de procese se afla in impas daca fiecare proces din serie asteapta un eveniment care poate fi cauzat doar de alt proces din serie. Deoarece toate procesele sunt in asteptare nici unul dintre ele nu va cauza vreodata unul din evenimentele care ar putea sa porneasca oricare alt membru al seriei si astfel, toate procesele asteapta la nesfarsit. In majoritatea cazurilor evenimentul pe care-l asteapta fiecare proces este eliberarea unei resurse detinuta in momentul respectiv de alt membru al seriei. Cu alte cuvinte fiecare membru al seriei de procese aflate in impas asteapta o resursa care este detinuta de un proces aflat in inpas. Nici unul dintre procese nu poate sa ruleze, nici unul dintre ele nu poate sa elibereze vreo resursa si nici unul nu poate fi repornit. Nu este important numarul proceselor si nici numarul si tipul resurselor detinute si solicitate.

Conditi de impas
Coffman et al. (1971) a aratat ca exista 4 conditii de impas: 1-Conditia de excludere reciproca. Ficare resursa este ori disponibila ori detinuta in mod curent de un singur proces. 2-Conditia retine si asteapta. Procesele care detin in mod curent resurse garantate anterior pot sa solicite noi resurse. 3-Conditia de nepreemtiune. Resursele garantate date anterior nu pot fi luate abuziv unui proces. Ele trebuie sa fie in mod explicit eliberate de catre procesul care le detine. 4-Conditia asteptarii circulare. Trebuie sa existe o inlantuire de doua sau mai multe procese fiecare dintre ele asteptand o resursa detinuta de urmatorul membru al inlatuirii. Toate aceste 4 conditii trebuie sa fie prezente pentru ca un impas sa apara. Daca una sau mai multe dintre aceste conditii nu apare impasul nu este posibil. 84

Aritoni Ovidiu

Sisteme de operare 1

Modelarea impasului
Holt(1972) a aratat ca aceste 4 conditii pot fi modelate folosind diagramele directionale. Diagramele au 2 tipuri de noduri: procese, reprezentate ca cercuri si resurse reprezentate prin patrate. Un arc de la un nod de resurse (patrat) la un nod de proces (cerc) arata ca resursa a fost solicitata anterior, acordata si momentan este detinuta de procesul respectiv. In figura 3-7(a) resursa R este acordata procesului A in acest moment.

Fig 3-7. Diagrama alocarii resurselor. (a) detinerea unei resurse. (b) solicitarea unei resurse. (c) impas. Un arc de la un proces la o resursa arata ca procesul este blocat in momentul actual si asteapta resursa respectiva. In figura 3-7(b) procesul B asteapta resursa S. in figura 3-7(c) vedem un impas: procesul C asteapta resursa T care este detinuta in mod curent de procesud D. Procesul D nu este pe punctul de-a elibera resursa T deoarece asteapta resursa U, detinuta de C. Ambele procese vor astepat la nesfarsit. Un ciclu in diagrama arata ca exista un impas in care sunt implicate procesele si resursele din ciclu. In acest exemplu ciclul este C-T-D-U-C. Acum sa vedem un exemplu despre modul de folosire al diagramelor de resurse. Avem 3 procese A,B si C si 3 resurse R,S si T. Solicitarile si eliberarile celor 3 procese sunt date in figura 3-8(a)-(c). Sistemul de operare este liber sa ruleze in orice moment orice proces care nu este blocat astfel ca ar putea decide sa ruleze A pana A isi termina sarcina, apoi sa ruleze B pana la sfarsit si, in final C. Aceasta ordonare nu duce la nici un impas (deoarece nu exista competitie pentru resurse) dar nici paralelism nu exista. Pe langa solicitarea si eliberarea de resurse, procesele calculeaza si fac I/O. atunci cand procesele sunt rulate secvential nu exista posibiliatatea ca, in timp ce un proces asteapta I/O altul sa poata folosi procesorul. De aceea se poate ca rularea proceslor strict secvential sa nu fie cea mai buna alegere. Pe de alta parte daca nici unul din procese nu face deloc I/O algoritmul intai cea mai scurta sarcina este preferabil in locul celui circular astfel ca in unele conditii rularea secventiala a tuturor proceselor poate fi cea mai buna alegere. Sa presupunem acum ca procesele fac atat I/O cat si calculare astfel ca algoritmul circular este un mod de temporizare rezonabil. Solicitarile de resursa ar putea aparea in 85

Aritoni Ovidiu

Sisteme de operare 1

ordinea din figura 3-8(d). Daca aceste 6 cereri sunt indeplinite in aceasta ordina cele 6 diagrame care rezulta sunt aratate in figura 3-8(e-j). Dupa ce solicitarea 4 a fost facuta A se blocheaza asteptan S ca in figura 3-8(h). In urmatorii 2 pasi si B si C se blocheaza, in cele din urma ducand la un ciclu si la impasul din figura 3.8(j). Totusi dupa cum am mentionat deja sistemului de operare nu I se cere sa ruleze procesele intro ordine anume. In particular, daca satisfacerea unei anumite cereri poate duce la impas sistemul de operare poate sa suspende pur si simplu procesul fara sa-I indeplineasca cererea (adica sa nu includa procesul in temporizare) pana la un moment favorabil. In figura 3-8 daca sistemul de operare ar sti despre iminenta impasului ar putea sa-l suspende pe B in loc sa-I acorde acestuia S. Daca rulam doar A si C vom obtine solicitarile si eliberarile din figura 3-8(k) in loc de cele din figura 3-8(d). aceasta secventa duce la diagrama de resursa din figurile 3-8(l-q), care nu duc la impas. Dupa pasul (q) procesului B ii poate fi acordat S deoarece A a terminat si C are tot ceea ce ii trebuie. Chiar daca B s-ar bloca in momentul solicitarii T, nu poate sa apara un impas. B va astepta pana C termina. Mai tarziu in acest capitol von studia un algoritm detaliat folosit pentru luarea deciziilor de alocare care nu duc la impas. Ceea ce trebuie sa intelegem acum este ca diagramele de resurse sunt un instrument care ne permite sa vedem daca o secventa cerere/eliberare data duce la impas. Pur si simplu ducem la bun sfarsit pas cu pas solicitarile si eliberarile si dupa fiecare pas verificam diagrama pentru a vedea daca nu contine un ciclu. Daca acest lucru se intampla avem un impas; daca nu, nu exista nici un impas. Desi aceasta analiza a diagramelor de resursa a fost facut pentru cazul in care exista o singura resursa din fiecare tip, diagramele de resursa pot fi si ele generalizate pentru a se ocupa de mai multe resurse de acelasi tip (Holt,1972). In general exista 4 strategii de rezolvare a impasurilor. 1.Pur si simplu sa se ignore problema 2.Detectare si remediere 3.Evitarea dinamica prin atenta alocare a resursei 4.Prevenirea prin negarea structurala a uneia dintre cele 4 conditii necesare pentru producerea impasului. In urmatoarele 4 sectiuni vom analiza pe rand fiecare din aceste metode.

C. Algoritmul strutului
Cea mai simpla metoda de abordare este algoritmul strutului: iti bagi capul in nisip si te prefaci ca nu exista nici o problema. Oamenii reactioneaza diferit fata de aceasta strategie. Matematicienii o gasesc inacceptabiala si spun ca impasurile trebuie prevenite prin orice mijloace. Inginerii intreaba cat de des eroneaza sistemul din alte motive si cat de grav este un impas. Daca impasurile apar, in medie o data la 50 de ani dar sistemul se prabuseste datorita erorilor de hardware, erori de compilare si bug-uri in sistemul de operare care apar o data pe luna majoritatea inginerilor nu ar fi dispusi sa piarda atat de mult din performanta sau avantaje pentru a elimina impasurile.

86

Aritoni Ovidiu

Sisteme de operare 1

fig. 3-8. Un exemplu pentru modurile cum apare un impas si felul in care poate fi evitat. Pentru a face acest contrast si mai specific, UNIX (si MINIX) pot suferi de impasuri care nici nu sunt detectate, ca sa nu mai vorbim de defectiunil automate. Numarul total de procese din sistem este determinat de numarul de intrari din tabla de procese. Astfel, slot-urile de pe tabla de procese sunt resurse limitate. Daca o comanda FORK esueaza din cauza ca tabla e plina, programul respectiv ar trebui sa astepte un timp si apoi sa incerce din nou. Acum sa presupunem ca un sistem UNIX are 100 de slot-uri pentru procese. 10 programe ruleaza, fiecare dintre ele avand nevoie sa creeze cate 12 sub-procese. Dupa ce fiecare a creat 9 procese, cele 10 procese initiale plus cele 90 de procese nou create au umplut tabla. Avem o situatie de impas deoarece fiecare dintre cele 10 procese initiale asteapta intr-un circuit fara nici un capat. Probabilitatea ca aceasta situatie sa apara este minima, dar este totusi posibil. Ar trebui sa abandonam procesele si comanda FORK pentru a rezolva problema? Si numarul maxim de fisiere deschise este limitat tot de marimea tablei pentru nod I, astfel ca o problema asemanatoare apare atunci cand acesta se umple. Spatiul de schimbare de pe disk este tot o resursa limitata. De fapt, aproape toate tablele din sistemul de operare reprezinta resurse limitate. Ar trebui sa le anulam pe toate pentru ca se poate intampla ca un numar n de procese sa ceara fiecare 1/n din total, si apoi fiecare sa incerce sa il ceara pe celalalt?

87

Aritoni Ovidiu

Sisteme de operare 1

Abordarea UNIX este de a ignora pur si simplu problema presupunand ca majoritatea utilizatorilor ar prefera un impas ocazional in locul unei reguli care sa restrictioneze utilizatorii la un singur proces, un singur fisier deschis, si asa mai departe. Daca impasurile ar putea fi eliminate pe gratis nu ar exista multe discutii pe tema asta. Problema este ca pretul este destul de mare, mai ales in ceea ce priveste restrictionarea proceselor, cum vom vedea mai incolo, lucru care este destul de neplacut. Astfel ca suntem in fata unei situatii neplacute in care trebuie sa alegem intre avantaje si corectitudine si a unei discutii aprinse despre care dintre ele este mai importanta.

D. Detectare si remediere
O a doua tehnica este detectarea si remedierea. Atunci cand este folosita aceasta tehnica sistemul nu face altceva decat sa monitorizeze solicitarile si eliberarile resurselor. De fiecare data cand o resursa este solicitata sau eliberata diagrama de resursa este actualizata si se verifica daca exista vreun ciclu. Daca exista, unul dintre procesele ciclului este omorat. Daca ciclul nu este intrerupt, un alt proces este oorat, si tot asa pana se intrerupe ciclul. O metoda mai dura este aceea in care nici macar nu se mentine diagrama de resursa, dar se verifica periodic daca exista vreun proces care a fost bloca fara intrerupere timp de o ora, de exemplu. Un astfel de proces este omorat. Strategia de detectare si remediere este adesea folosita pentru computerele principale mari, in special in sistemele de incarcare in care este acceptabila omorarea si apoi restartarea uni proces. Totusi trebuie sa se aiba grija ca toate fisierele modificate sa fie readuse la starea lor initiala prcum si sa se anuleze oricare alt efect secundar care este posibil sa fi aparut.

E. Prevenirea impasurilor
O a treia strategie pentru impasuri este impunerea unor restrictii adecvate proceselor, astfel incat, din punct de vedere structural un impas sa fie imposibil. Cele patru conditii stabilite de Cauffman et al. (1971) furnizeaza un indiciu pentru posibile solutii. Daca ne putem asigura ca cel putin una din aceste conditii nu este indeplinita niciodata, atunci impasurile sunt imposibile (Havender, 1968). Mai intai sa analizam conditia excluderii reciproce. Daca nici o resursa nu ar fi alocata doar unui singur proces impasurile nu ar putea sa apara. Totusi, este la fel de clar ca daca permitem ca doua procese sa foloseasca imprimanta in acelasi timp vom crea o stare de haos. Prin spiralarea iesirii de imprimanta, mai multe procese vor putea sa scoata rezultatele in acelasi timp. In acest model singurul proces care cere efectiv imprimanta fizica este daemon-ul de imprimanta. De vreme ce acest daemon nu solicita niciodata alta resursa, putem sa eliminam posibilitatea unui impas in ceea ce priveste imprimanta. Din pacate, nu toate dispozitivele pot fi spiralate (tabla de procese nu se preteaza la spiralare). In plus, chiar competitia pentru spatiul de disk care poate fi spiralat poate sa duca la impas. Ce s-ar intampla daca ar exista doua procese si fiecare sa umple jumatate din spatiiul de spiralat si n-ar fi incheiat niciunul dintre ele? Daca daemonul ar fi programat sa inceapa printarea chiar inainte ca toate rezultatele sa fie spiralate, se poate 88

Aritoni Ovidiu

Sisteme de operare 1

ca imprimanta sa nu lucreze daca un proces de iesire ar decide sa astepte cateva ore pana la prima iesire. Din acest motiv, in mod normal daemon-urile sunt programate sa inceapa sa printeze doar cand este disponibil intregul fisier de iesire. Nici un proces nu va termina vreodata, deci avem un impas de disk. Cea de-a doua conditie formulata de Coffman et al. arata mul mai promitator. Daca putem sa impiedicam procesul care detine resursele sa astepte mai multe resurse, putem sa evitam impasurile. Un mod de a realiza acest lucru este sa cerem proceselor sa solicite resursele inainte de a incepe executarea. Daca toate resursele ar fi disponibile, procesului I-ar fi alocata orice resursa de care are nevoie si ar putea sa ruleze pana la sfarsit. Daca una sau mai multe resurse ar fi ocupate, nimic n-ar fi alocat si procesul ar astepta pur si simplu. O mare problema a acestui tip de abordare este faptul ca multe procese nu stiu inainte de momentul cand incep sa ruleze de cate resurse vor avea nevoie. O alta problema este aceea ca daca folosim acest mod de abordare resursele nu vor fi utilizate in mod optim. De exemplu, sa ne gandim ca un proces care citeste date de pe o banda de intrare, analizeaza timp de o ora, apoi scrie rezultatul pe banda si il scoate pe plotter. Daca toate aceste resurse ar trebui solicitate dinainte, procesul va ocupa unitatea de iesire pe banda si plotter-ul timp de o ora. Un mod putin diferit de a nu indeplini conditia retine si asteapta este sa cerem procesului care solicita o resursa sa elibereze mai intai, pentru un timp toate resursele pe care le detine. Numai daca aceasta cerere este indeplinita poate procesul sa-si primeasca resursele inapoi. Abordarea celei de-a treia conditii (fara preemptiune) este si mai putin promitatoare decat a celei de-a doua. Daca unui proces I-a fost alocata imprimanta si se afla in mijlocul printarii rezultatului, vom crea dezordine daca ii luam abuziv imprimanta deoarece plotter-ul de care are nevoie nu este disponibil. A mai ramas o singura conditie. Asteptarea circulara poate fi eliminata in mai multe moduri. Unul dintre ele este stabilirea unei reguli care sa interzica proceselor sa detina mai mult de o resursa odata. Daca are nevoie de o a doua resursa trebuie sa elibereze prima resursa. Pentru un proces care trebuie sa copieze un fisier foarte mare de pe o banda pe o imprimanta aceasta restricie este inacceptabila. Un alt mod de a evita asteptarea circulara este furnizarea unei numerotari globale a tuturor resurselor, asa cum se vede in figura 3-9(a). acum regula este urmatoarea: procesele pot sa solicite resurse in orice moment, dar toate solicitarile trebuie facute in ordine numerica. Un proces poate sa solicite intai o imprimanta si apoi o unitate de banda, dar nu poate sa solicite intai un plotter si apoi o imprimanta.

Figura 3-9. (a) Resurse ordonate numeric. (b) O diagrama de resursa. 89

Aritoni Ovidiu

Sisteme de operare 1

Cu aceasta regula, diagrama alocarii resurselor nu poate sa aiba cicluri. Sa vedem in figura 3-9(b) de ce acest lucru este valabil si pentru cazul in care exista doua procese. Un impas poate sa apara doar daca A solicita resursa j si B solicita resursa i. Daca presupunem ca i si j sunt resurse diferite, ele vor avea numere diferite de ordine. Daca i>j, atunci A nu are voie sa solicite j. Daca i<j, atunci B nu are voie sa solicite i. Oricum, un impas este imposibil. Se procedeaza la fel si in cazul in care exista mai multe procese. In fiecare moment, una dintre resursele alocate va avea pozitia cea mai de sus. Procesul care detine aceasta resursa nu va mai putea sa solicite alta resursa deja alocata. Ori va temina, ori, in cel mai rau caz, va solicita o resursa de pe o pozitie superioara, dintre cele disponibile. In cele din urma va termina si va elibera resursele pe care le detine. In acest moment, alt proces va primi resursa si va putea sa termine si el. Pe scurt, este un scenariu in care toate procesele termina, deci nu apare nici un impas. O variatie minora a acestui algoritm este sa se ceara ca resursele sa fie obtinute strict in ordine crescatoare si sa insiste doar asupra faptului ca nici un proces sa nu solicite o resursa situata mai jos decat cea pe care o detine deja. Daca, initial un proces solicita resursele 9 si 10, si apoi le elibereaza pe amandoua, efectiv se incepe de la inceput, deci nu exista nici un motiv sa se interzica de acum incolo solicitarea resursei 1. Desi ordonarea numerica a resurselor elimina problema impasurilor, se poate gasi o ordonare care sa satisfaca pe toata lumea. Atunci cand resursele include si sloturile tablei de procese, spatiul de spiralare al disk-ului, baza de date cu inregistrarile blocate si ale resurse abstracte, numarul resurselor potentiale si utilzarile diferite pot fi atat de numeroase incat nici un fel de ordonare nu ar putea functiona. Diferitele abordari pentru prevenirea impasurilor sunt rezumate in figura 3-10.

Fig. 3-10. Rezumat al abordarilor folosite pentru prevenirea impasurilor.

F.Evitarea impasului
In figura 3-8 am vazut ca impasul a fost evitat nu prin impunerea unor reguli arbitrare pentru procese, ci prin analizarea atenta a fiecarei solicitari de resursa pentru a vedea daca poate fi acordata in deplina siguranta. Se punu urmatoarea intrebare: exista un algoritm care sa evite intotdeauna impasurile prin luarea celei mai bune decizii? Raspunsul este un da hotarat putem saevitam impasurile, dar numai daca anumite informatii sunt disponibile dinainte. In aceasta sectiune vom analiza modurile de evitare a impasurilo printr-o atenta alocare a resurselor. Algoritmul bancherului pentru o singura resursa 90

Aritoni Ovidiu

Sisteme de operare 1

Un algoritm de temporizare care poate sa evite impasurile il datoram lui Dijkstra (1965) si este cunoscut sub denumirea de algoritmul bancherului. Este conceput dupa modul in care un bancher dintr-un oras mic ar putea sa trateze un grup de client carora lea acordat linii de credit. In figura 3-11(a) vedem patru clienti si fiecaruia dintre ei I-a fost acordat un anumit numar de unitati de credit (ex. o unitate este 1Kdolari). Bancherul stie ca nu toti clientii vor avea imediat nevoie de cantitatea maxima a creditului lor, astfel ca si-a rezervat pentru a ii servi doar 10 unitati in loc de 22 . (in aceasta analogie clientii reprezinta procesele, unitatile sunt, de exemplu, unitatile de banda si bancherul reprezinta sistemul de operare). Clientii isi conduc afacerile facand din cand in cand cereri de imprumut. La un moment dat, apare situatia aratata in figura 3-11(b). o lista de clienti care arata banii deja imprumutati (unitati de banda deja alocate) si creditul maxim dispoibil in cazul lor (numarul maxim de unitati de banda de care vor avea nevoie mai tarziu) se numeste starea sistemului in ceea ce priveste alocarea resurselor. Despre o stare se poate spue ca e sigura atunci cand exista o secventa de alte stari care face ca toti clientii sa primeasca imprumuturi in limitele creditului lor (toate procesele sa-si primeasca toate resursele si sa termine). Starea din figura 3-11(b) este sigura deoarece, cu doua unitati ramase, bancherul poate sa intarzie orice solicitare in afara de cea a lu Marvin, lasandu-l astfel pe Marvin sa termine si sa elibereze toate cele patru resurse pe care le detine. Cu inca patru unitati, bancherul poate sa acorde unitatile necesare fie Barbarei, fie Suzannei, etc.

fig 3-11. trei stari de alocare a resurei: (a) sigura; (b) sigura; (c) nesigura Ganditi-va ce s-ar intampla daca ar fi aprobata o solicitare a Barbarei pentru una sau mai multe unitati (vezi fig. 3-11(b)). Am avea situatia din figura 3-11(c), care nu este sigura. Daca brusc, toti clientii si-ar solicita creditul maxim, bancherul nu ar putea satisface nici una din aceste cereri si s-ar ajunge la un impas. O stare nesigura nu duce neaparat la un impas deoarece se poate ca acel client sa nu aiba nevoie de intregul credit disponibil, dar bancherul nupoate sa se bazeze pe acest lucru. Prin urmare, algoritmul bancherului presupune analizarea fiecarei cereri pe masura ce acestea apar si verificarea daca satisfacerea ei duce la o stare sigura. Daca da, cererea este satisfacuta; altfel, este amanata. Pentru a vedea daca o stare este sigura, bancherul verifica daca are suficiente resurse pentru a satisface clientul la maxim. Daca are aceste resurse, clientul este platit din nou si urmatorul client care este cel mai aproape de limitele sale este verificat, si asa mai departe. Daca toate imprumuturile pot fi replatite inseamna ca starea este sigura si cererea initiala poate fi satisfacuta.

91

Aritoni Ovidiu

Sisteme de operare 1

Traiectoriile resurselor
Algoritmul de mai sus a fost descris in termenii unei sigure clase de resurse (ex. doar unitati de banda sau doar imprimante, dar nu ambele). In figura 3-12 vedem un model pentru a trata cu doua procese si cu doua resurse, de exemplu o imprimanta si un plotter. Axa orizontala reprezinta numarul de instrunctiuni executate de procesul A. axa verticala reprezinta numarul de instrunctiuni executate de procesul B. La momentul I1 A solicita o imprimanta; la momentul I2 are nevoie de un plotter. Imprimanta si plotter-ul sunt eliberate la momentele I3 si respectiv I4. Procesul B are nevoie de plotter de la momentul I5 la momentul I7 si de imprimanta de la momentul I6 la momentul I8. Fiecare punct din diagrama reprezinta o stare reunita a acestor doua procese. Initial, starea este in punctul p, cand nici un proces nu a executat nici o instructiune. Daca temporizatorul il alege pe A pentru a rula primul, ajungem in punctul q in care A a executat un numar de instructiuni, dar B nu a executat niciuna. In punctul q traietoria devine verticala, indicand faptul ca temporizatorul a decis ca B sa ruleze. Cand avem un singur procesor toate caile trebuie sa fie orizontale sau verticale, niciodata pe diagonala. In plus, miscarea se face intotdeauna spre nord sau spre est, niciodata spre sud sau spre vest (procesele nu pot rula inapoi).

Fig. 3-12 Doua traiectorii proces-resursa. Cand A intersecteaza linia I1 in timp ce parcurge calea de la r la s, solicita si ii este acordata imprimanta. Cand B ajunge in punctul t, solicita plotter-ul. Zonele hasurate sunt in mod special interesante. Zonele cu linii inclinate de la sud-vest spre nord-est reprezinta ambele procese care detin imprimanta. Regula excluderii reciproce face imposibil accesul in aceasta zona. In acelasi mod zona hasurata reprezinta ambele procese care detin plotter-ul si este la fel, imposibil de accesat. Daca sistemul intra vreodata in casuta delimitata de I1 si I2 lateral si de I5 si I6 sus si jos, va ajunge in impas la intersectia dintre I2 si I6. In acest punct Acere plotter-ul si B cere imprimanta si ambele sunt deja acordate. Intreaga casuta este nesigura si trebuie 92

Aritoni Ovidiu

Sisteme de operare 1

evitata. In punctul t singurul lucru sigurul lucru sigur este rularea procesului A pana ajunge la I4. Dincolo de acesta va fi buna orice traiectorie spre u.

Algoritmul bancherului pentru resurse multiple


Acest model de diagrama este greu de aplicat in cazul general al unui numar arbitrar de procese si de clase de resurse, fiecare cu mai multe exemplare (ex. doua plotter-e, trei unitati de banda). Totusi, algoritmul bancherului poate fi generalizat pentru a indeplini aceasta sarcina. In figura 3-13 vedem cum functioneaza. In figura 3-13 vedem doua matrice. Cea din stanga arata cate resurse din fiecare tip sunt in mod curent alocate fiecaruia dintre cele cinci procese. Matricea din dreapta, arata de cate resurse mai are nevoie fiecare proces pentru a se incheia. Ca in cazul cu o singura resursa, procesele trebuie sa anunte totalul de resurse de care au nevoie, inainte de a incepe saexecute, astfel incat sistemul sa poata calcula la fiecare pas matricea din dreapta.

Fig. 3-13 Algoritmul bancherului cu mai multe resurse Cei trei vectori din dreapta figurii arata resursele existente E, resursele detinute P si A - resursele disponibile. De la E stim ca sistemul are sase unitati de banda, trei plotter-e, patru imprimante si doua unitati CD-ROM. Dintre acestea, cinci unitati de banda, trei plotter-e, patru imprimante si doua unitati CD-ROM sunt in mod curent alocate. Acest fapt poate fi vazut prin adunarea coloanelor cu cele patru resurse din matricea din stanga. Vectorul de resurse disponibile este diferenta dintre ceea ce are sistemul si ceea ce se utilizeaza in mod curent. Algoritmul prin care se verifica daca o stare este sigura sau nu poate fi acum formulat. Cautati un rand R ale carui nevoi nesatisfacute de resurse sunt mai mici sau egale cu A. Daca nu exista un astfel de rand, in cele din urma sistemul va ajunge in impas deoarece nici un proces nu se poate incheia. Sa presupunem ca procesul din randul ales solicita toate resursele de care are nevoie (lucru care este garantat a fi posibil) si se incheie. Marcam faptul ca procesul a terminat si adaugam toate resursele sale vectorului A.

93

Aritoni Ovidiu

Sisteme de operare 1

Repetam pasii 1 si 2 pana cand fie toate procesele se incheie, caz in care starea iniiala era sigura, fie pana cand apare un impas, caz in care inseamna ca acea stare nu e sigura. Daca mai multe procese sunt potrivite pentru a fi alese la pasul 1, nu are importanta care dintre ele este selectat : cantitatea de resurse ori se mareste, ori, in cel mai rau caz, ramane aceeasi. Acum sa ne intoarcem la exemplul din figura 3-13. starea curenta este sigura. Sa presupunem ca procesul B solicita in acest moment o imprimanta. Aceasta cerere poate fi indeplinita deoarece deoarece si starea urmatoare este sigura (procesul D poate sa termine si apoi procesele A sau E, urmate de celelalte). Acum sa ne inchipuim ca dupa ce i se acorda lui B unul dintre cele doua imprimante ramase E vrea sa obtina ultima imprimanta. Satisfacerea acestei cereri ar reduce vectorul resurselor disponibile la (1 0 0 0), care duce la impas. In mod evident cererea lui E nu ppoate fi satisfacuta imediat si trebuie amanata pentru un timp. Acest algoritm a fost publicat de catre Dijkstra pentru prima data in 1965. de atunci, aproape fiecare carte despre sistemele de operare a descris in detaliu acest altgoritm. Au fost scrise nenumarate lucrari despre diferite aspecte ale acestui altgoritm. Din pacate, putini autori au avut indrazneala sa sublinieze ca desi este minunat in teorie, in practica este aproape inutil deoarece deoarece sunt putine cazurile in care procesele stiu dinainte care vor fi nevoile lor maxime de resurse. In plus, numarul proceselo nu este fix, ci variaza in mod dinamic pe masura ce utilizatorii intra sau ies din sistem. Mai mult chiar, resursele care se astepta sa fie disponibile pot sa dispara brusc (unitatile de banda se pot strica. Pe scurt, schemele descrise anterior sub denumirea prevenire sunt foarte restrictive, iar algoritmul descris aici ca evitare necesita informatii care de obicei nu sunt disponibile. Daca va puteti gandi la un algoritm general care face aceste lucruri si in practica nu numai in teorie, scrieti-l si trimiteti-l. Pentru cazuri particulare de aplicatii exista multe algoritmuri speciale excelente. De exemplu, in multe sisteme de baze de date, o operatie care apare frecvent cere blocarea catorva inregistrari si apoi actualizeaza toate inregistrarile blocate. Atunci cand mai multe procee ruleaza in acelasi timp exista un real pericol de impas. O abordare des intalnita este numita blocare in doua faze. In prima faza procesul incearca sa blocheze toate inregistrarile de care are nevoie, una cate una. Daca reuseste face actualizarile si elibereaza inregistrarile. Daca vreo inregistrare e deja blocata, elibereaza inregistrarile pe care le detine deja si incepe din nou. Intr-un fel aceasta abordare se aseamana cu solicitarea in avans a tuturor resurselor necesare sau cel putin inainte de a se face ceva ireversibil. Totusi, aceasta strategie nu este general valabila. In sistemele in timp real si in sistemele de control al proceselor de exemplu, nu se accepta ca un proces sa se incheie inainte de a ajunge la sfarsit si sa inceapa de la inceput din cauza ca o resursa nu est disponibila. Nu se accepta nici sa inceapa din nou daca procesul a scris sau a citit mesaje din retea, a actualizat fisiere sau daca a facut orice altceva care nu pote fi repetat in siguanta. Algoritmul functioneaza doar in acele situatii in care programatorul a aranjat lucrurile foarte atent, astfel incat programul poate fi oprit in orice moment al primei faze si apoi restartat. Din pacate, nu toate aplicatiile pot fi structurate in acest mod.

94

Aritoni Ovidiu

Sisteme de operare 1

Anexa 1

Procese sub Windows NT

Convenii de limbaj la programarea Windows


Limbajul nativ de dezvoltare a aplicaiilor Windows este C ++. Din aceast cauz, n cele ce urmeaz vom descrie principiile programrii folosind construcii C i C ++. Headerul <windows.h> conine principalele construcii de limabaj folosite n interfaa Windows.

Constante
n <windows.h> se definesc o serie de constante. Numele acestora este compus din dou pri: o prim parte indic grupul din care face parte constanta, apoi caracterul _ i n final numele specific, de regul suficient de lung nct s sugereze ce reprezint. Iat cteva nume de grupe: CS SW IDC IDI DT WS WM stilul clasei de ferestre; crearea ferestrei; identificator de cursor; identificator de icon; atribut de afiare texte; stilul ferestrei; mesaj asociat unei ferestre

De exemplu, pentru fixarea stilului unei clase se pot lega prin operatorul C | (sau) constantele de mai jos (care nu sunt singurele, mai pot fi i altele): - CS_DBLCLIKS mesajele se transmit ferestrei prin dublu click; - CS_HREDRAW sau CS_VREDRAW provoac redesenarea ferestrei dup o redimensionare orizontal/vertical.

Tipuri de date
Windows folosete o serie de tipuri de date noi, prin care s-a urmrit creterea protabilitii aplicaiilor n cazul unor noi arhitecturi de calculatoare. Astfel, avem tipurile: - BOOL, BYTE, DWORD (32 bii); - FARPROC (pointer spre funcie); - LPSTR (pointer ctre string); - LPMSG (pointer ctre o structur MSG) etc. Pentru desemnarea obiectelor sunt definite nite tipuri de date speciale: descriptor sau handle. Acestea sunt ntregi pe 16 bii prin intermediul crora se pot referi obiecte. Tipurile de handle folosite sunt:

95

Aritoni Ovidiu HANDLE HBRUSH HCURSOR HICON HMENU HWND

Sisteme de operare 1 indicator general; indicator general spre obiect pensul; indicator spre resurs cursor; indicator spre icon; indicator spre o resurs meniu; indicator indicator spre o fereastr.

Nume de variabile
Atribuirea de nume pentru variabile se face respectndu-se anumite convenii, provenit din experiena programatorilor. Este vorba de notaia ungar de denumire a variabilelor. [114]. Ele nu sunt restricii impuse de sistem, dar este de preferat s fie respectate. De regul numele atribuite sunt lungi, ncep cu liter mic, iar n cadrul numelor apar litere mari la nceputurile cuvintelor care le compun. De multe ori, cnd este vorba de o singur variabil de un anumit tip, numele ei este numele tipului, scris cu liter mic. Tot ca i convenii, nceputurile (prefixele) numelor de variabile au semnificaie: b pentru BOOL; by pentru BYTE; c pentru char; dw pentru DWORD; fn pentru funcie; h pentru handle; i pentru int; lp petru pointer lung; w pentru WORD etc.

Aplicaii consol
n ceea ce privete programarea Windows, prezenta lucrare nu are, nici pe departe, intenia de a o descrie exhaustiv. Vom aborda doar ceea ce este strict necesae pentru a putea evidenia aspectele de concuren posibile, n contextul cadru, multiplatform, al demersurilor noastre. Cele mai simple aplicaii care se pot scrie sub Windows NT sunt aplicaiile consol. Acestea sunt, n fapt, aplicaii cu intrare i ieire standard n mod text, la fel ca i la programele simple sub Unix. Spre exemplu, un program extrem de simplu este programul prim.cpp de mai jos (Programul 3.6): int main (int c, char* a [ ] { int i; char n [120]; printf (Numele? ); gets (n); printf ( Salut %s\nUrmeaza parametrii liniei de comanda\n, n); for (i=0; a[i]; i++)

96

Aritoni Ovidiu printf (%s\n, a[i] ); return 0; }

Sisteme de operare 1

Programul 3.6. O aplicaie consol: prim.cpp


Presupunem c n urma compilrii i link-editrii acestui program s-a obinut filierul executabil prim.exe. O execuie a lui se face ntr-o fereastr MSDos Prompt (fereastr Cmd) de sub WindowsNT. Dac se lanseaz programul prin comanda: > prim 11111 doi trei333 4 i se d la cerere numele (unuia dintre autori). E:\FLORIN> prim.exe 11111 doi trei333 4 Numele? Florian Boian Salut Florian Boian Urmeaza parametrii liniei de comanda Prim.exe` 11111 doi trei333 4 E:\FLORIN>

Programul 3.5. Rezultatul execuiei programului prim.exe


Un al doilea exemplu de aplicaie consol simpl este un program filtru. Acesta citete linie cu linie de la intrarea standard i d la ieire aceleai linii, scurtate la primele 10 caractere. Sursa Filtru.cpp este prezentat n continuare (Programul 3.7.). #include <stdio.h> #include <string.h> int main (int c, char* a [ ] ) { char 1 [128]; for (; ;) { if (gets(1) = = NULL) break; if (strlen (1) > 10) 1 [10] = 0; printf (%s\r\n, 1); } 97

Aritoni Ovidiu return 0; }

Sisteme de operare 1

Programul 3.7. Sursa Filtru.cpp Lansarea unui astfel de filtru se face, de asemenea, dintr-o fereastr Cmd, putndu-se, la fel ca n Unix sau Dos, s se redirecteze intrarea i ieirea lui standard, astfel: Filtru.exe <FisierIntrare >FisierIesire Cum se ajunge de la aceste surse cpp la fiierele executabile corespunztoare? Aceasta depinde de mediul cpp cu care se deyvolt aplicaiile. Nu intenionm o prezentare exhaustiv a acestor medii, deoarece nu constituie obiectul prezentei lucrri. Vom expune, strict telegrafic, paii realizrii lor folosind mediul DevStudio pentru Microsoft Visual C++ 6.0. 1. n meniul File se selecteaz New, n fereastra de dialog obinut se selecteaz Project. 2. n cadrul acesteia se selecteaz Win32 Console Application. 3. n spaiul Project Name se scrie numele proiectantului, n cazul nostru prim sau filtru. 4. n spaiul Location se trece locul n structura de directori, n care mediul i va dezvolta aplicaia, de exemplu \Useri\florin Aici, mediul creeaz un subdirector cu numele proiectului (n cazul nostru prim sau filtru). 5. Se alege tipul de aplicaie consol dorit: An empty project; A simple application, A Hello world! application; An application that supports MFC. Considerm c n acest exemplu am ales: A simple application. 6. Dup Ok, se afieaz un mesaj de informare, iar n subdirectorul din location sunt create subdirectoarele: SourceFiles, HeaderFiles,

ResourceFiles.
98

Aritoni Ovidiu

Sisteme de operare 1

De asemenea, este depus acolo un fiier ReadMe.txt n care se explic rolul fiecrui fiier sau director creat de mediu. 7. Se selecteaz din menioul FileView, se expandeaz directorul cu numele proiectului, apoi subdirectorul SourceFiles n care un fiier cu numele proiectului i tipul cpp. Acest fiier surs conine, gata generat, scheletul programului principal (al funciei main). Dup un dublu click pe numele acestuia, el apare n fereastra de editare. 8. Din acest moment programatorul poate s scrie efectiv coninutul aplicaiei sale, plecnd de la scheletul furnizat de mediu. 9. La terminare, meniul Build ofer, printre altele, posibilitatea de a compila surs respectiv (Compile sau Ctrl+F7), respectiv s obin un fiier exe (Build sau F7). 10. Fiierul de tip exe obinut este plasat n subdirectorul Debug al directorului cu numele proiectului. El poate fi lansat n execuie din mediu sau dinafara lui, poate fi copiat n alt parte (cum l-am depus noi pe prim.exe n e:florin) i lansa de acolo, etc. Crearea unui proces Windows Crearea unui proces n Windows NT se face prin apelul funciei CreateProcess de ctre un thread (fir de execuie) dintr-un alt proces. Funcia are urmtorul prototip: BOOL CreateProcess ( LPCTSTR lpszImageName, LPCTSTR LPSECURITY_ATTRIBUTES LPSECURITY_ATTRIBUTES BOOL DWORD LPVOID lpvEnvironment, LPTSTR LPSTARTUPINFO LPROCESS_INFORMATION ) }

lpszCommandLine, lpsaProcess, lpsaThread, fInheritHandles, fdwCreate, lpszCurDir, lpsiStartInfo, lppiProcInfo

Atunci cnd un fir de execuie apeleaz funcia CreateProcess, sistemul creeaz un spaiu de adresare i ncarc noul proces n acest spaiu. Dup aceast operaie, sistemul creeaz threadul primar pentru noul proces i-l lanseaz n execuie. 99

Aritoni Ovidiu S vedem semnificaia parametrilor funciei CreateProcess: lpszImageName

Sisteme de operare 1

Parametrul identific numele fiierului executabil n care este memorat codul pentru procesul ce se va crea. CreateProcess va cuta fiierul mai nti n directorul curent, i apoi n directorele descrise de variabila de mediu PATH. Dac acest parametru este NULL, funcia va lua numele fiierului din primul cuvnt al liniei de comand specificat de parametrul lpszCommandLine. lpszCommandLine Parametrul specific argumentele care trebuie transmise ctre noul proces. La pornirea procesului, aceste argumente vor fi regsite n argumentul lpszCmdLine al funciei WinMAin. lapszCommandLine puncteaz ctre un ir de caractere ANSI. lpsaProcess i lpsaThread Identific atributele de securitate care trebuie date noului proces i threadului su primar. Dac valorile lor sunt NULL, sistemul va furniza valori implicite pentru aceti parametri. fInheritHandles Specific modul n care se motenesc referinele la obiecte de ctre procesul fiu. n mod normal, n Windows NT acestea nu sunt aceleai pentru fiecare proces. Chiar dac este vorba de acelai obiect sistem, procese diferite pot lucra cu valori diferite. Dac dorim ca aceste valori s fie identice n procesul tat i n procesul fiu, atunci putem specifica valoarea TRUE acestui program. fdwCreate Conine comutatorii (flags) ce afecteaz modul n care este creat noul proces. Se pot specifica mai muli comutatori combinndu-I prin operatorul |. lpvEnvironment Refer un bloc de memorie n care sunt memorate irurile, care descriu variabilele de mediu ce trebuie utilizate de noul proces. De obicei, valoarea acestui paramteru trenuie s fie NULL, caz n care procesul fiu primete aceleai variabile de mediu ca i printele. lpszCurDir 100

Aritoni Ovidiu

Sisteme de operare 1

Parametrul permite specificarea unui nou disc i a unui nou director curent pentru procesul nou creat. Dac valoarea transmis pentru acest parametru este NULL, directorul i discul de lucru ale noului proces sunt aceleai ca li cele ale procesului printe. lpsiStartInfo Puncteaz ctre o structur STARTUPINFO. Aceste informaii sunt necesare pentru subsistemul Win32 la crearea unui nou proces. Aceast structur este prea complex pentru a o descrie aici. S reinem doar c n ea se pot specifica: caracteristicile unei ferestre consol: o culoare; o numr de linii; o coloane; o poziie pe ecran; o titlu, etc.; informaii despre modul n care va fi afiat fereastra aplicaiei: o maximizat; o icon, etc.; informaii despre comportarea sistemului n timpul ncrcrii aplicaiei: o forma cusorului, etc.

lppiProcInfo Conine adresa unei structuri care va fi completat cu informaii de ctre funcia CreateProces nainte ca aceasta s-i termine execuia. Aceast structur va conine referinele pentru noul proces, pentru threadul su primar, precum i identificatorii acestora. Structura este declarat astfel: typedef struct _PROCESS_INFORMATION { HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } PROCESS_INFORMATION;

Terminarea unui proces Windows


Un proces poate fi terminat pe dou ci: apelnd din interior funcia EixtProcess 101

Aritoni Ovidiu sau aplnd din exterior funcia TerminateProcess.

Sisteme de operare 1

Este preferabil prima cale, cea de-a doua trebuie folosit doar pentru situaii extreme. Prototipul funciei ExitProcess este: VOID ExitProcess (UINT fuExitCode); Funcia termin procesul care a apelat-o i i seteaz acestuia codul de retur pe valoarea fuExitCode. Funcia TerminateProcess are urmtorul prototip: BOOL TerminateProcess (HANDLE hProcess, UINT fuExitCode); Cu aceast funcie, un proces poate termina orice alt proces din sistem, inclusiv pe el nsui. Procesul teminat este dat de referina hProcess. Codul de retur a procesului terminat va fi setat pe valoarea parametrului fuExitCode. Folosirea funciei TerminateProcess poate fi periculoas la o programare nengrijit. n mod normal, evenimentul de terminare a unui proces este semnalat de ctre Windows NT tuturor DLL-urilor ataate de proces. La terminarea procesului, folosind funcia TerminateProcess, aceste DLL-uri nu vor fi avertizate, producndu-se eventuale pierderi de date. Windows NT garanteaz totui c toate resursele sistem utilizate de proces vor fi eliberate indiferent cum este terminat procesul. Exemplu de creare proces sub Windows Exemplul care urmeaz este similar celui din Programul 3.3. Aplicaia consol creeaz un proces fiu, n care se va face rezumatul directorului curent, lansnd n acest scop comanda sistem dir. nainte de a prezenta programul DirWindows.cpp, introducem rutina err_sys, corespunztoare sursei 3.1, de data aceasta, n dou variante (Programul 3.8.). La fel ca sub Unix, vom folosi una din cele dou funcii err_sys, n cazul unor diverse apeluri de funcii Windows, care eueaz. #include <assert.h> //afiseaza textul si termina programul int err_sys (char *text) { puts (text); exit (1); } //er_sys

102

Aritoni Ovidiu Programul 3.8. Sursele err_sys.cpp

Sisteme de operare 1

(Sub unele implementri, rolul funciei noastre err_sys poate fi preluat de ctre un apel sistem numit perror.) Programul 3.9. prezint sursa DirWindows.cpp. #include stdafx.h #define STRICT #include <windows.h> #include <stdio.h> #include err_sys.cpp int main ( ) {

STARTUPINFO si = { sizeof (si) }; PROCESS_INFORMATION pi; BOOL b = CreateProcess (rezumat.bat, NULL, NULL, NULL, FALSE, 0, NULL, NULL &si, &pi); if ( b ) { // Asteapta procesul sa-si inceapa executia (v. mai jos) Sleep (1000); // Am considerat necesar acest timp de asteptare pt. // a permite sistemului sa creeze procesul inainte // de a testa terminarea lui if (TerminateProcess (pi.hProcess, 2) ) { DWORD dwT, dwP; GetExitCodeProcess (pi. hProcess, &dwP); // obtine codul de retur al thread-ului principal GetExitCodeThread (pi.hThread, &dwT); if ( dwT ! = 2 ) printf (Cod de retur incorect pentru proces); if ( dwT ! = 2) printf (Retur incorect pentru thread principal); CloseHandle (pi. hProcess); CloseHandle (pi. hThread); Printf (\nExecutie cu succes\n); } else err_sys (GetLastError ( ) ); } else err_sys (eroare la lansare rezumat.bat\n); return 0; } 103

Aritoni Ovidiu

Sisteme de operare 1

Programul 3.9. Sursa DirWindows.cpp Precizm c dac procesul creat i ncheie execuia nainte de apelul TerminateProcess ( ), acest apel returneaz ERROR_ACCESS_DENIED. Lnsm pe seama cititorului s modifice acest exemplu, scriind un program propriu care s fie lansat n cadrul procesului fiu.

Anexa 2

Pipe sub Windows NT

n Windows NT, exist dou posibiliti de a folosi pipe n IPC. O prim variant este pipe anonime, care se pot folosi numai pentru comunicarea ntre procese de pe aceeai main. A doua variant este pipe cu nume, folosite pentru comunicarea ntre procese ce opereaz nu neaprat pe aceeai main NT. Pipe anonim Windows Ne vom ocupa mai nti de pipe anonime, ca i mecanism IPC n programarea concurent sub Windows NT. Un pipe anonim poate fi folosit, ca i pipe-ul de sub Unix, pentru comunicarea ntre procese descendente din creatorul pipe-ului. n urma crerii, procesul creator poate trimite fiilor (nepoilor etc.) handle-urile pipe-ului, n momentul crerii proceselor fii prin apeluri ale funciei CreateProces ( ) (vezi 3.1.3.3). Pentru ca fiul s moteneasc handle-ul la pipe, printele trebuie s seteze parametrul fInheritHandle, din apelul CreateProces ( ), la valoarea TRUE. Un pipe fr nume se creeaz folosind apelul CreatePipe ( ). Pipe-ul se nchide cu ajutorul funciei CloseHandle ( ). Funcia CreatePipe ( ) creeaz un pipe fr nume i are urmtorul prototip: BOOL CreatePipe (PHANDLE phRead, PHANDLE phWrite, LPSECURITY_ATRIBUTES lpsa, DWORD cbPipe ) Funcia ntoarce TRUE n caz de succes sau FALSE la eec. phRead i phWrite Sunt pointerii spre cele dou handle-uri (de citire i de scriere) obinute n urma crerii. lpsa - Parametrul are o dubl semnificaie: determin dac handle-ul la pipe, returnat de funcie poate fi motenit n procesele fii, proprietate care are loc pentru o valoare diferit de NULL. Acelai parametru reprezint un descriptor de securitate. Dac se specfic pentru acest parametru valoarea NULL, sistemul va fixa atributele de securitate implicite. 104

Aritoni Ovidiu

Sisteme de operare 1

cbPipe

- Specific dimensiunea buferului rezervat pentru operaiile de I/O prin pipe. Dac aceast valoare este 0, atunci dimensiunea implicit a buferului o stabilete sistemul de operare.

Scrierea i citirea din pipe-urile anonime se face folosind funciile ReadFile ( ) i WriteFile ( ). Prototipurile acestora sunt date n 3.2.3.2. Operaiile sunt atomice. O citire va opri procesul pn cnd va reui s se execute. n mod similar, o scriere va bloca procesul pn cnd va avea suficient spaiu n pipe pentru efectua operaia de scriere dorit. Att procesul creator, ct i procesele fii care motenesc cele dou handle-uri ale pipe-ului, le pot folosi ntre momentul primirii lor i momentul nchiderii. Astfel, procesul creator poate ncepe imediat s foloseasc pipe prinapelurile ReadFile ( ) i WriteFile ( ). Dup creare i primirea handle-urilor, procesele fii pot s foloseasc la rndul lor funciile ReadFile ( ) i WriteFile ( ) pentru a citi sau scrie din pipe. Urmtorul exemplu, o nou soluie a problemei propoziiilor (3.2.1.2.), demonstreaz modul de folosire al pipe-urilor anonime ntre un proces printe i procesul su fiu. Pipe-ul anonim i procesul fiu sunt astfel create nct fiul s moteneasc de la printe handle-ul de citire. Programul PropozitiiPipeScriitor.cpp citete de la intrarea standard liniile de text i le depune n pipe. Programul PropozitiiPipeCititor.cpp primete de la printe handle-ul de citire din pipe, citete din pipe i afieaz propoziiile la ieirea lui standard. Procesul printe creeaz un pipe anonim i un proces fiu, cruia i trimite, prin linia de coman, handle-ul de citire din pipe. Apoi i depune n pipe succesiunea de linii citite de la intrarea lui standard. Programul 3.26 prezint sursa acestuia, iar Programul 3.27 sursa PropozitiiPipeCititor.cpp. # include <windows.h> # include <stdio.h> # include <stdlib.h> # include <memory.h> # include err_sys.cpp # include scriitorInPipe.c # define MESSAGE_SIZE 1000 int cdecl main (int argc, char **argv) { DWORD dwCodDeReturn, dwOctetiCititi; int iFiu, iContor; SECURITY_ATTRIBUTES saAtribute: STARTUPINFO siInfo; PROCESS_INFORMATION piFiu; HANDLE hPipeCitire, hPipesScriere; // Configurarea atributelor de securitate // cu care pipe/ul va fi mostenit 105

Aritoni Ovidiu

Sisteme de operare 1 );

memset (&sAtribute, 0xoo, sizeof (SECURITY_ATTRIBUTES) saAtribute.nLength = sizeof (SECURITY_ATTRIBUTES); saAtribute.bInheritHandle = TRUE;

// Crearea unui pipe anonim if (CreatePie (&hPipeCitire, // Handle de citire din pipe &hPipeScriere, // Handle pentru scrierea in pipe &saAtribute, // Atribute de securitate MESSAGE_SIZE // Dimensiune bufer pentru pipe ) = = False) err_sys (Eroare la creare pipe\n); // Trimite clientului handle de pipe prin care sa poata citi // prin crearea corespunzatoare a liniei de comanda TCHAR wszLiniaDeComanda [ MAX_PATH ]; sprintf ( wszLiniaDeComanda, fiu %d, hPipeCitire); // Creare proces fiu memset ( &siInfo, 0x00, sizeof (STARTUPINFO) ); siInfo.cb = sizeof (STARTUPINFO); siInfo.lpTitle = Proces fiu; if (CreateProcess (NULL, // Pointer la nume modul executabil wszLiniaDeComanda, // Linia de comanda &saAtribute, // Atrib. de securitate pt. proces &saAtribute, // Atrib. de securitate pt. thread TRUE, // mosteneste toate handle-urile CREATE_NEW_CONSOLE, // Atrib. suplimentare NULL, // Variabila de mediu NULL, // Directorul curent &siInfo, // Informatii start &piFiu // Aici returnare informatii // despre procesul fiu ) = = FALSE) err_sys (Eroare la crearea procesului fiu \n); scriitorInPipe (hPipeScriere); // Asteapta sa termine procesul fiu do { if (GetExitCodeProcess (piFiu.hProcess, &dwCodDeReturn) = = FALSE) err_sys (Eroare la GetExitCodeProcess\n); (dwCodDeReturn = = STILL_ACTIVE) Sleep (1); } while (dwCodDeReturn = = STILL_ACTIVE); CloseHandle (hPipeScriere); 106 if

Aritoni Ovidiu Return (0); }

Sisteme de operare 1

Programul 3.26. Sursa PropozitiiPipeScriitor.cpp #include <windows.h? #include <stdio.h? #include <stdlib.h? #include <memory.h> #include cititorDinPipe.c int cdecl main (int argc, char **argv) { HANDLE hPipeCitire; // obtine un handle de citire din pipe hPipeCitire = (HANDLE) atol (argv [1]); // apeleaza rutina de citire din pipe cititorDinPipe (hPipeCitire); CloseHandle (hPipeCitire); return (0); } Programul 3.27. Sursa PropozitiiPipeCititor.cpp Pipe cu nume sub windows Pipe cu nume este un mecanism de comunicare ntre dou sisteme diferite, ambele fiind operaionale pe platforme din clasa Microsoft: Windows 95, 98, 2000, NT, precum i platforme mai vechi, ca OS/2, Novell, DOS (numai client). Este un IPC bidirecional, cu faciliti apropiate de cele ale comunicrii prin socket [11]. n figura 3.10 sunt prezentate succesiunile apelurilor sistem, att pentru server, ct i pentru client. Cititorul poate uor observa particularizrile necesare pentru comunicarea prin pipe anonim. 1. 2. 3. 4. 5. 6. CreateNamedPipe ConnectNamedPipe ReadFile WriteFile DisconnectNamedPipe CloseHandle CloseHandle

1. CreateFile 2. ReadFile 3. WriteFile 4.

Server

Pipe cu nume

Server
107

Aritoni Ovidiu

Sisteme de operare 1

Figura 3.10. Comunicarea prin pipe cu nume sub Windows Crearea unui pipe cu nume se face prin apelul sistem: CreateNamedPipe, cu prototipul: HANDLE CreateNamedPipe ( LPSTR numePipe, DWORD optiuniModOpen, DWORD optiuniModPipe, DWORD nMaxInstances, DWORD lungBufOut, DWORD lungBufIn, DWORD timeOut, LPSECURITZ_ATTRIBUTES lpsa ) unde: numePipe Este un string prin care se indic numele pipe-ului. Conveniile Microsoft de specificare a acestor nume impun dou sintaxe, una pentru pipe local i alta pentru pipe de pe o alt main. Aceste specificri sunt: \\.\PIPE\numePipePeMAsina \\adresaMasina\PIPE\numePipePeMasina adresa mainii este fie o specificare Internet, fie o adres IP [1]. Atenie! n constantele string de specificare a acestor nume, fiecare caracter \ trebuie dublat, aa cum cer regulile de evitare specifice limbajului C. optiuniModOpen Specific direcia de deschidere a pipe-ului. Valoarea lui poate fi una dintre constantele: PIPE_ACCESS_DUPLEX, PIPE_ACCESS_INBOUND, PIPE_ACCESS_OUTBOUND, indicnd fie ambele sensuri, fie numai de la client la server, fie numai de la server spre client. 108

Aritoni Ovidiu optiuniModPipe

Sisteme de operare 1

Precizeaz caracteristicile acestui pipe. Pentru specificare, se folosesc constante sau combinaii legate ntre ele prin operatorul |. PIPE_TYPEBYTE, PIPE_TYPE_MESSAGE pentru scrierea ca flux de octei, respectiv ca i mesaj; PIPE_READMODE_BYTE, PIPE_READMODE_MESSAGE pentru citirea dup regulile fluxului de octei sau citirea ca i mesaj; PIPE_WAIT, PIPE_NOWAIT pentru comunicarea sincron, respectiv asincron. nMaxInstances Specific numrul de clieni care se vor conecta la acest pipe. La nevoie, se poate folosi constanta PIPE_UNLIMITED_INSTANCES. lungBufOut i lungBufIn Specific dimensiunile bufferelor, pentru ieire i intrare. Sistemul ia aceste numere doar ca sugestii, n funcie de context el putnd s redimensioneze aceste buffere. timeOut Indic, n milisecunde, durata maxim de ateptare. lpsa Specific atributele de securitate. De cele mai multe ori se specific NULL, lsnd astfel pe seama sistemului fixarea acestora. Apelul sistem ntoarce un handle, care va fi folosit ca i argument n celelalte apeluri sistem legate de pipe. Dup crearea unui pipe cu nume, serverul apeleaz: ConnectNamedPipe (HANDLE hNamedPipe; LPOVERLAPPED lpo= Primul handle este cel ntors de crearea pipe. Al doilea parametru, de regul NULL, indic faptul c se ateapt la conectare pn cnd un client se conecteaz efectiv la pipe. (A se compara aceast regul cu cea similar de la FIFO de sub Unix). La fel ca i la pipe anonime, se folosesc apelurile ReadFile i WriteFile pentru schimbul cu pipe. Serverul i ncheie activitatea apelnd: 109

Aritoni Ovidiu

Sisteme de operare 1

DisconnectNamedPipe (HANDLE hNamedPipe); CloseHandle )HANDLE hNamedPipe); Pentru client, conectarea la un pipe cu nume presupune un apel sistem CreateFile Descriem aici, prototipurile funciilor de lucru cu fiiere sub Windows. HANDLE CreateFile ( LPCTSTR numeFisier, DWORD acces, DWORD partajare, LPSECURITY_ATTRIBUTES descr_sec, DWORD mod_deschid, DWORD atributeFisier, HANDLE fis_atrib ); unde: numeFisier - Este numele fiierului care se va crea. acces - Este modul de acces (n citire i/sau scriere). partajare - Este modul de partajare a fiierului. mod_deschid - Este modul de creare a fiierului. atributeFisier - Sunt atribute fi;ier. n cazul crerii unui pipe cu nume, numeFisier reprezint numele pipe-ului, cu sintaxa specificat mai sus, la apelul CreateNamedPipe. HFILE OpenFILE ( LPCSTR numeFisier, LPOFSTRUCT lpBuf, UINT uActiune ); unde: numeFisier Este numele fiierului care se va deschide. lpBuf - Este pointer la o structur care reine informaii despre fiier. uActiune - Indic operaia care se va efectua asupra fiierului. BOOL WriteFile ( HANDLE hFisier, LPCVOID lpBuf, DWORD nNrOctetiDeScris, LPDWORD lpNumarOctetiScrisi, 110

Aritoni Ovidiu LPOVERLAPPED lStructIO ); unde:

Sisteme de operare 1

hFisier - Este handle-ul fisierului n care se va scxrie. lpBuf - Este pointer la datele care se vor scrie n fiier. nNrOctetiDeScris - Este num de octei de scris. 1pNumarOctetiScrisi - Este pointer la numrul de octei scrii efectiv. lpStructIO - Este de obicei are valoarea NULL. BOOL RedaFile ( HANDLE hFisier, LPCVOID lpBuf, DWORD nNrOctetiCititi, LPOVERLAPPED lpStructIO ); unde: hFisier - Este handle-ul fiierului din care se va citi. lpBuf - Este pointer la un bufer n care se vor citi datele. nNrOctetiDeScris - Este numr de octei de citit. lpNumarOctetiCititi - Este pointer la numrul de octei citii efectiv. lpStructIO - Este de obicei are valoarea NULL. BOOL CloseHandle (HANDLE hObject); unde: hObject - Este handle-ul la un obiect deschis. Pentru mai multe informaii legate de prototipurile acestor funcii, se recomand consultarea documentaiei MSDN [83]. Drept exemplu de utilizare a acestui pipe, vom da nc o soluie a problemei propoziiilor. Considerm c att programul scriitor (n pipe), ct i programul care citete din pipe se gsesc pe aceeai main. Spre deosebire de pipe sub Unix, n cazul Windows creatorul resursei pipe trebuie s fie activ, pentru ca eventualii scriitori sau cititori s poat comunica folosind pipe-ul respectiv. De aceea, vom include operaia de creare a pipe-ului n programul care scrie date n pipe. Programul 3.28 indic sursa scriitorului n pipe (care este i creatorul resursei pipe), iar Programul 3.29 indic sursa cititorului din pipe. #include scriitorInPipe.c #include <winbase.h> #include err_sys.cpp 111

Aritoni Ovidiu main ( ) {

Sisteme de operare 1

Handle hNamedPipe; // creeaza pipe/ul cu numele propoz hNamedPipe = CreateNamedPipe (\\\\.\\PIPE\\propoz, PIPE_ACCESS_OUTBOUND | FILE_FLAG_WRITE_THROUGH, PIPE_TYPE_BYTE | PIPE_WAIT, 3, dimBufIn, DimBufOut, TMOUT, NULL); err_sys (hNamedPipe! = INVALID_HANDLE_VALUE); // asteapta sa se conecteze un client ConnectNamedPipe (hNamedPipe, NULL); // apeleaza rutina de scriere in pipe scriitorInPipe (hNamedPipe); DisconnectNamedPipe (hNamedPipe); CloseHandle (hNamedPipe); } Programul 3.28. Sursa PropozitiiFifiScriitor.cpp #include #include #include #include <windows.h> <stdio.h> cititorDinPipe.c err_sys.cpp

main ( ) { HANDLE hNamedPipe; // deschide pipe/ul in citire hNamedPipe = CreateFile (*\\\\.\\PIPE\\propoz, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); err_sys (hNamedPipe! = INVALID_HANDLE_VALUE); // apeleaza rutina de citire din pipe cititorDinPipe (hNamedPipe); ClosedHandle (hNamedPipe); } Programul 3.29. Sursa PropozitiiFifoCititor.cpp

112

Aritoni Ovidiu

Sisteme de operare 1

Invitm cititorul s construiasc programele corespunztoare surselor 3.22. (SemnaturaFifoScriitor.c) i 3.23 (SemanaturaFifoCititor.c), n cazul mecanismului de comunicare pipe cu nume, sub Windows.

ANEXA 3 Comunicarea ntre procese Windows prin memorie partajat


Fiiere I/O mapate n memorie i zone partajate Maparea (gzduirea) fiierelor n memoria intern este o facilitate preluat de Windows NT de la sistemul de operare DOS. Aceast mapare permite aplicaiilor s acceseze pri ale fiierului mapat folosin pointeri din memoria intern, n loc de accesare a discului. Prin aceasta se obine o vitez de acces mult mai mare. Printre alte avantaje ale maprii, mai amintim faptul c se beneficiaz de mecanismul de cache-ing i de paginare a memoriei interne, oferit de Windows NT. O aplicaie poate mapa fiiere de la 1 octet pn la 2G octei. Fiierele mapate n memorie permit, de asemnea, ca dou sau mai multe procesoare s partajeze aceste fiiere i implicit s partajeze memoria intern. n continuare, prezentm o succesiune de 5 (cinci) pai ce trebuie urmai de orice aplicaie Windows care folosete o zon de memorie partajat: 1. Crearea segmentului de memorie partajat CreateFileMapping. Aceast operaie se poate realiza dou moduri: a.) b.) folosind funcia

folosind un fiier definit anterior de ctre utilizator, cu ajutorul apelurilor CreateFile sau OpenFile. Folosind o pagin sistem, specificat cu ajutorul unui handler predefinit, cu valoarea 0xFFFFFFFF.

Dac segmentul de memorie partajat exist deja, deschiderea accesului la segment se obine cu ajutorul funciei OpenFileMapping. Obiectul Windows, asociat segmentului de memorie partajat, poart numele de file-mapping. Att funcia CreateFileMapping, ct i funcia OpenFileMapping ntorc un handle la obiectul file-mapping asociat segmentului de memorie partajat referit. 2. Maparea propriu-yis a segmentului de memorie partajat (reprezentat prin obiectul file-mapping), n spaiul de memorie al procesului curent, este realizat cu ajutorul apelului MapViewOfFile. Aceast funcie ntoarce un pointer la o poriune din aceast memorie partajat. 3. Pointerul obinut n urma apelului precedent, permite aplicaiei apelante s acceseze zona de memorie partajat n citire i/sau scriere, n funcie de parametrii specificai la apel. 113

Aritoni Ovidiu

Sisteme de operare 1

4. Operaia complementar celei de mapare, se realizeaz cu ajutorul apelului UnmapViewOfFile. Astfel, se realizeaz detaarea aplicaiei curente de la segmentul de memorie partajat, prin eliberarea spaiului de memorie ocupat prin operaia de mapare. 5. n final, nchiderea handle-ului la obiectul file-mapping se realizeaz cu funcia CloseHandle. De asemenea, folosind CloseHandle, se nchide fiierul deschis cu CreateFile sau OpenFile. Crearea/deschiderea n varianta 1.b, cu handle-ul special 0xFFFFFFFF permite folosirea unei singure zone partajate n sistem. Folosind numai acest handle, NU este posibil ca pe acelai sistem s existe mai multe zone de memorie partajat. Pentru a permite ca fiecare grup de procese s-i foloseasc propria zon de memorie partajat, trebuie s se foloseasc crearea/deschiderea n varianta 1.a, CreateFile/OpenFile. Astfel, se creeaz/deschide cte un fiier mapat n memorie pentru fiecare zon de memorie partajat dorit. n continuare, punctm o comparaie, la nivel API, ntre operaiile de lucru cu memorie partajat sub Unix i sub Windows: CreateFileMapping - -> shmget MapViewOfFile - -> shmat UnmapViewOfFile - -> shmdt CloseHandle - -> shmctl Sintaxa exact a funciilor implicate n utilizarea segementelor de memorie partajat sub Windows, va fi descris mai jos. Prototipurile funciilor CreateFile, ReadFile i WriteFile au fost prezentate n 3.2.3.2. Prototipurile celorlalte funcii folosite sunt descrise n continuare: HANDLE CreateFileMapping ( HANDLE hFis, LPSECURITY_ATTRIBUTES descr_sec, DWORD prot, DWORD maxHigh, DWORD maxLow, LPCTSTR nume_file_mapping ); unde: - Este handle la fiierul de mapat; valoarea 0xFFFFFFFF pentru acest parametru indic o pagin implicit sistem. descr_sec - Este descriptor de securitate; dac se specific valoarea NULL pentru acest parametru, sistemul va folosi atributele de securitate implicite. prot - Este atributul de protecie pentru obiectul de mapat. 114 hFis

Aritoni Ovidiu

Sisteme de operare 1

maxHigh i maxLow - Compun dimensiunea pe 32 de bii a obiectului de mapat. nume_file_mapping - Este numele obiectului file mapping HANDLE OpenFileMapping ( DWORD acces, BOOL bHandleMostenire, LPCTSTR nume_file_mapping ); unde: acces - Indic modul de acces (citire i/sau scriere). bHandleMostenire - Indic dac obiectul file-mapping va fi motenit de eventuale procese fii. nume_file_mapping - Este numele obiectului file-mapping. LPVOID MapViewOfFile ( HANDLE hFileMap, DWORD acces, DWORD offsetHigh, DWORD offsetLow, DWORD nrOctetiDeMapat ); unde: hFileMap Este handle la obiectul file-mapping (handle returnat de CreateFileMapping). acces Indic modul de acces (citire i/sau scriere). offsetHigh i offsetLow - Compun offsetul pe 32 de bii, a zonei de memorie de mapat. nrOctetiDeMapat Este numrul de octei de mapat. BOOL UnmapViewOfFile (LPCVOID lpAdresaMapata); unde: lpAdresaMapata Este adresa de memorie unde ncepe maparea Pentru mai multe informaii legate de semnificaia parametrilor i prototipurilor funciilor ce opereaz cu memorie partajat sub Windows, se recomand consultarea documentaiei MSDN. Implementarea foii de calcul sub Windows Aplicaia de mai jos implementeaz calculul tabelar pentru problema definit n 3.3.1. Programul 3.35 este fiierul header al aplicaiei, similar Programului 3.31. 115

Aritoni Ovidiu

Sisteme de operare 1

#include <assert.h> #include <ctype.h> #include <stdio.h> #include <time.h> #include <winsock2.h> #include <windows.h> #include semnaturaTemporala.cpp #define SMAX 1000 struct foaie_de_calcul { char s[4] [100]; int v[4]; }; #define LUNFIME siyeof (struct foaie_de_calcul) #define NUME_SEGMENT_MEMORIE_PARTAJATA MemoriaMeaPartajata Programul 3.35. Fiierul header memPartFoaieWin.h Fiierul header definete foaia de calcul, lungimea acesteia i definete numele segmentului de memorie partajat. La fel ca n cazul comunicrii folosind pipe, i mecanismul de comunicare folosind memorie partajat, sub Windows, presupune c creatorul obiectului file-mapping este activ, ct timp scriitorii i cititorii partajeaz resursa respectiv. De aceea, vom include operaia de creare a obiectului file-mapping n programul care acceseaz obiectul file-mapping n scriere. Sursele programele scriitor i cititor sunt prezentate n Programul 3.36, respectiv 3.37. #include memPartFoaieWin.h // 0 #define NR_ITER 100 int main ( ) { int it, shmd, i, x,; struct foaie_de_calcul *mp; char s [SMAX]; HANDLE handleMemoriePartajata; // creeaza obiectul file-mapping handleMemoriePartajata = CreateFileMapping ( (HANDLE) 0XFFFFFFFF, NULL, PAGE_READWRITE, 0, sizeof (struct foaie_de_calcul), NUME_SEGMENT_MEMORIE_PARTAJATA); 116

Aritoni Ovidiu assert (handleMemoriePartajata! = NULL);

Sisteme de operare 1

mp = (struct foaie_de_clacul *)MapViewOfFile ( handleMemoriePartajata, FILE_MAP_WRITE, 0, 0, 100); assert (mp! = NULL); // 1 for (it = 0; it<NR_ITER; Sleep (1000*(rand( ) % 2) ), it + + { i = rand ( ) % 3 ; x = 1 + rand ( ) % 99; strcpy (s, semanaturaTemporala ( ) ); // 2 strcpy (mp - >s [i], s); mp -> v [3] = mp -> v [3] - mp ->v [i] + x; mp -> v [i] = x; strcpy (mp -> s[3], s); //3 } UnmapViewOfFile (mp); CloseHandle (handleMemoriePartajat); //4 } Programul 3.36. Sursa memPartScriitorFoaie.cpp #include memPartFoaieWin.h #define NR_ITER 50 int main ( ) { int it, shmd, i, x, j; struct foaie_de_calcul *mp, *copie; char s [SMAX]; HANDLE handleMemoriePartajata; // deschide un obiect file-mapping handleMemoriePartajata = OpenFileMapping ( FILE_MAP_READ, 0, NUME_SEGMENT_MEMORIE_PARTAJATA); assert (handlerMemoriePartajata! = NULL); mp = (struct foaie_de_calcul *) MapViewOfFile (handleMemoriePartajata, FILE_MAP_READ, 0, 0, 0); assert (mp! = NULL); copie = (struct foaie_de_calcul * ) malloc (sizeof (struct foaie_de_calcul ) ); 117

Aritoni Ovidiu

Sisteme de operare 1

for (it = 0; it<NR_ITER; Sleep (1000 * (rand ( ) % 2 ) ), it ++) { for (j=0;j<4; j++) { copie -> v[j] = mp -> v [j]; strcpy (copie) -> s [j], mp -> s[j] ); } strcpy (s, semanaturaTemporala ( ) ); x = copie -> v [3] copie -> v [0] copie -> v[1] copie -> v[2]; i = o; if (strcmp (copie -> s[3], copie -> s[0] ) && strcmp (copie -> s [3], copie -> s[1]) && strcmp (copie -> s[3], copie -> s [2]) ) i = 1; printf (citire: %s, s); if (i) printf (\tSemnatura total eronata!); if (x) printf (\%d este diferenta la total!, x); printf (\n); for (i=o; i<4; i++) printf (%s\t%d\n, copie -> s [i], copie -> v [i] ); printf (\n); } UnmapViewOfFile (mp); CloseHandle (handleMemoriePartajata); } Programul 3.37. Sursa memPartCititorFoaie.cpp

118

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