Sisteme Software

=== SISTEME SOFTWARE ===

Software de sistem

Introducere

Un program este o “vrajă” aruncată asupra unui computer, transformând datele intrate in mesaje cu eroare

Anonim –

De – alungul carierei tale, ai putea fi în poziția de a fi obligat să cumperi hard suboptim pentru calculator pentru că un anumit sistem este singurul care rulează un anumit produs software de care are nevoie angajatul tau. Deși ai fi tentat să vezi această situație ca pe o insultă la buna ta judecată, trebuie să recunoști că un sistem complet cere atât soft, cât si hard. Softul este fereastra prin care utilizatorii văd un sistem. Dacă softul nu poate furniza servicii in concordanță cu așteptările utilizatorilor, ei văd intregul sistem ca inadecvat, indiferent de calitatea hardului său.

In capitolul 1 am introdus o organizare a computerului care constă in șase nivele masina, cu fiecare nivel deasupra nivelului porții furnizând o preocupare (abstractie) pentru stratul de sub el. În capitolul patru am discutat asamblatorii și relația limbajului de asamblare cu arhitectura. În acest capitol studiem softul găsit la nivelul al treilea si legăm aceste idei cu softul la al patrulea si al cincilea nivel. Colectia de soft la aceste trei nivele funcționeaza sub programele de aplicare și chiar deasupra nivelului arhitectural al setului de instrucțiuni. Acestea sunt compo-nentele softului, “mașinile”, cu care interacționează codul sursei aplicației tale. Programele la aceste nivele lucrează împreună pentru a asigura accesul la resursele hardului care poartă comenzile conținute în programele aplicației. Dar să privești un sistem de computer ca și cum ar fi un singur fir care merge de la codul sursei aplicației până la nivelul poartă, înseamnă să-ți limitezi întelegerea asupra a ceea ce este computer. Am ignora bogatul set de servicii furnizate la fiecare nivel.

Deși modelul nostru pentru un sistem de computer plasează doar sistemul de operare la nivelul “softului sistemului”, studiul softului de sistem include adesea compilatorii si alte utilităti, precum și o categorie de programe complexe numite uneori middleware.

În general vorbind, middleware-ul este o clasificare vastă (largă) pentru softul care oferă servicii deasupra nivelului sistemului de operare, dar dedesubtul nivelului programului aplicației.

Probabil vă amintiți că în capitolul 1 am discutat despre diferența semantică ce există între componentele fizice și limbajele și aplicațiile de înalt nivel. Știm că această diferență semantică nu trebuie să fie perceptibilă pentru utilizator, iar middleware-ul este softul care furnizează invizibilitatea necesară. Deoarece sistemul de operare este fundatia pentru tot softul sistemului, virtual tot softul sistemului interactionează într-o anumită măsură cu sistemul de operare. Începem cu o scurtă introducere asupra operațiilor interne ale sistemelor de operare și apoi continuăm cu straturile mai înalte de soft.

8.2 Sisteme de operare

Original, principalul rol al unui sistem de operare era să ajute diferitele apli-cații să interacționeze cu hardul computerului. Sistemele de operare furnizează un set necesar de funcțiuni, permițând pachetelor softului să controleze hardul computerului. Fără un sistem de operare, fiecare program pe care îl rulezi ar avea nevoie de propriul său driver pentru placa video, placa de sunet si așa mai departe.

Deși sistemele moderne de operare încă au această funcție, așteptările utilizatorilor asupra sistemelor de operare s-au schimbat considerabil. Ei presupun că un sistem de operare va face mai usor pentru ei să se descurce cu sistemul și cu resursele sale. Această așteptare a zămislit (a produs) managementul fișierului “drag and drop”, precum și managementul dispozitivului “plug and play”.

Din perspectiva programatorului, sistemul de operare ascunde detaliile nive-lelor arhitecturale scăzute ale sistemului, permitând o concentrare mai mare pe rezolvarea problemelor de nivel inalt. Am văzut că este dificil să programezi la nivelul mașinii sau la nivelul limbajului de asamblare.

Sistemul de operare funcționează cu numeroase componente soft, creând un cadru mai prietenos în care resursele sistemului sunt utilizate efectiv și eficient și unde nu se cere programarea în cod mașină. Sistemele de operare furnizează nu numai această interfață programatorului, ci și acționează de asemenea ca un strat între softul aplicației și hardul mașinii. Indiferent dacă îl privești prin ochii utiliza-torului sau ca liniile codului unei aplicații, sistemul de operare este, in esență o mașină virtuală care furnizează o interfață de la hard la soft. Lucrează cu dispozitive reale și dispozitive reale.

Sistemul de operare însuși este puțin mai mult decât o piesă obișnuită de la soft. Diferă de majoritatea altor softuri prin aceea că este încărcat prin boot-area computerului și este apoi executat direct de către procesor. Sistemul de operare trebuie să aibă control asupra procesorului, (precum și a altor resurse), pentru că una din sarcinile sale este să organizeze procesele care foosesc CPU, fie renunță la CPU și așteaptă alte resurse.

După cum am menționat, sistemul de operare este o interfață importantă pentru hardul de dedesubt (fundamantal), atât pentru utilizatori cât și pentru programele de aplicație. In plus față de rolul său ca și interfață, el mai are trei sarcini principale. Managementul procesului este probabil cel mai interesant dintre acestea trei. Celelalte două sunt managementul resursei sistemului și protecția acelor resurse de procesele țintă. Inainte de a discuta aceste îndatoriri, haideți să privim o istorie a dezvoltării sistemelor de operare pentru a vedea modul cum merge paralel cu evoluția hardului de computer.

8.2.1 Istoria sistemelor de operare.

Sistemele de operare de astăzi se luptă pentru ușurința optimă de utilizare, furnizând o abundență de unelte grafice pentru a ajuta atât utilizatorii novici, cât și pe cei experimentați. Dar nu a fost întotdeauna la fel. Doar cu o generație in urmă resursele de computer erau atât de prețioase încât fiecare ciclu de mașină a trebuit să facă o muncă folositoare. Datorită costului enorm al hardului computerului, timpul computerului a fost distribuit cu multă grijă. În acele zile, dacă doreai să folosești un computer, primul tău pas era să-ți acorzi timp pentru mașină. Când timpul tău sosea, alimentai singur dintr-un pachet de carduri perforate pornind mașina in mod interactiv, cu un singur utilizator. Înainte de a încărca programul tău, totuși, trebuia mai întâi să incarci compilatorul. Setul inițial de carduri din pachetul de introdus includea efortul celui care încărca și care făcea ca restul cardurilor să fie încărcate. În acest punct, puteai să-ți alcătuiești programul. Dacă era o eroare în codul tău trebuia să o găsești repede, să perforezi din nou cardul (sau cardurile) greșite și să introduci din nou pachetul în calculator într-o altă încercare de a-ți alcătui programul. Dacă nu puteai localiza rapid problema, trebuia să-ți iei mai mult timp și să incerci mai târziu. Dacă programul tău se alcătuia, următorul pas era să legi codul tău subiect de fișierele codului bibliotecă pentru a crea fișierul executabil care de fapt va rula. Aceasta era o pierdere teribilă de timp pentru computer și persoană. În efortul de a face hardul folosibil de către mai mulți oamnei, s-a introdus procesarea în grup. Cu procesarea în grup operatorii profesio-nali au combinat cardurile în grupuri sau baloți cu instrucțiunile corespunzătoare permițându-le să fie procesate cu intervenție minimă.

Aceste grupuri erau de obicei programe de tipuri similare. De exemplu putea fi un grup de programe FORTRAN si apoi un grup de programe COMBOL. Aceasta i-a permis operatorului să seteze mașina pentru programe FORTRAN, să le citească și să le execute pe toate, iar apoi să treacă la COMBOL. Un program numit monitor rezident permitea programelor să fie procesate fără interacțiune umană (alta decât plasarea pachetelor de carduri în cititorul de carduri).

Monitoarele au fost precursorii sistemelor de operare moderne. Rolul lor era direct (simplu): monitorul începea treaba, dădea controlul computerului asupra sa, iar când treaba era făcută, monitorul relua controlul mașinii. Munca făcută la început de oameni era făcută de computer, crescând astfel eficiența și utilizarea. După cum își amintesc autorii, totuși, timpul de răspuns în cazul grupurilor era destul de mare. (Ne reamintim vechile zile ale cardurilor cu limbaj de asamblare pentru procesoare la centrul de date. Eram emoționați la ideea de a aștepta pentru orice mai puțin de 24 ore înainte să primim înapoi rezultatele). Procesarea cu grupuri făcea debugging-ul dificil, sau mai corect, foarte consumaroare de timp. Un inel infinit într-un program putea face ravagii într-un sistem. În cele din urmă s-au adăugat cronometre monitoarelor pentru a preveni monopolizarea sistemului de către un proces. Totuși, monitoarele aveau o limitare severă prin aceea că nu furnizau nici o protecție adițională. Fără protecție, o lucrare de grup putea afecta lucrările nerezolvate (de exemplu o lucrare „rea” putea citi prea multe carduri, redând astfel incorect următorul program). Mai mult, era posibil pentru o lucrare de grup să afecteze chiar codul monitorului! Pentru a rezolva această problemă, sistemele computerului erau echipate cu hard specializat, permițând computerului să opereze fie în mod monitor, fie în mod utilizator. Programele erau rulate în mod utilizator, trecând la mod monitor când erau necesare anumite sisteme.

Creșterile în performanța CPU au făcut procesarea cu grupuri de carduri perforate din ce în ce mai puțin eficientă. Banda magnetică oferea o posibilitate de a procesa pachetele de carduri mai rapid. Cititorii și tipăritorii de carduri erau conectați la computere mai mici, care erau folosite pentru a citi pachetele de carduri pe bandă. O bandă putea conține câteva lucrări. Aceasta permitea CPU să treacă în mod continuu printre procese fără a citi cardurile. O procedură similară a fost urmată pentru produs. Produsul era scris pe bandă, care era apoi înlocuită și pusă pe un computer mai mic care efectua tiparirea propriu-zisă. Era necesar pentru monitor să verifice periodic dacă o operațiune I/O era necesară. Cronometrii erau adăugați lucrării pentru a permite scurte întreruperi pentru ca monitorul să poată trimite I/O nerezolvate la unitațile benzii. Aceasta permitea socotelilor I/O și CPU să survină în paralel. Acest proces, predominant în ultima parte a anilor 60 până în ultima parte a anilor 70, era cunoscut ca Operație Periferică Simultană Online, sau SPOOL – ing (rulare) și este cea mai simplă formă de multiprograma-re. Cuvântul a rămas în vocabularul de computer, dar sensul lui contemporan se referă la produsul tipărit care este scris pe disc înainte de a fi trimis la tipăritor.

Sistemele multiprogramare (stabilite în ultima parte a anilor 60 și continuând până în prezent) extind ideea „rulării” (SPOOLING) și a procesării de grup pentru a permite câtorva programe executabile să fie în memorie în mod concomitent. Acest lucru este realizat făcând cicluri prin procese, permițand fiecăruia să folosească CPU pentru o perioadă de timp specifică. Monitoarele erau capabile să facă față multiprogramării până la un anumit punct. Ele puteau începe lucrări, rula operații, reliza I/O, schimba între lucrările utilizatorilor și da ceva protecție între lucrări. Trebuia să fie clar, totuși, că lucrarea monitorului devenea mai complexă, necesitând soft mai elaborat. Acesta a fost punctul în care monitoarele au evaluat softul pe care acum îl știm ca sistem de operare.

Deși sistemele de operare au ușurat o cantitate semnificativă de muncă, utilizatorii doreau o interacțiune mai strânsă cu computerele. În particular, concep-tul de lucrări perforate era neatrăgător. N-ar fi frumos dacă utilizatorii ar putea termina lucrările lor și ar primii feedback (reultat, răspuns) imediat?

Sistemele timesharing (care împărțeau timpul) permiteau exact acest lucru. Terminalele erau conectate la sisteme care permiteau accesul de către utilizatori considerați multipli. Procesarea de grup a fost cuând demodată, ca și facilitate interactivă de program pentru împărțirea timpului (de asemenea cunoscută ca „timeslicing”). Într-un sistem de împărțire a timpului, CPU comută între sesiunile utilizatorilor foarte repede acordând fiecărui utilizator o porție mică de timp de procesor. Această procedură de comutare între procese este numită comutare în context. Sistemele de operare realizează rapid aceste comutări în context, dând utilizatorului o mașină virtuală personală.

Cronometrul, permite multor utilizatori să împartă o singură aplicație. Sisteme interactive mari, cum ar fi sistemele de rezervare a liniilor aeriene, servesc mii de utilizatori simultani. Cu sistemele de împărțire a timpului, mari utilizatori interactivi de sistem nu sunt conștienți de utilizarea sistemului de către alți utilizatori.

Introducerea multiprogramării și a împărțirii timpului cerea un soft mai complex pentru sistemele de operare. În timpul unei comutări de context, toată informația despre procesul în executare curentă trebuie să fie salvată, astfel încât când procesul este planificat să folosească CPU din nou, ea poate fi stocată în aceeași stare în care a fost salvată.

Aceasta cere ca sistemele de operare să cunoască toate detaliile hardului. Amintiți-vă din capitolul 6 că în sistemele de azi se folosesc memoria virtuală și paginarea.

Tabelele de pagini și alte informații asociate cu memoria virtuală trebuie să fie salvate în timpul unei comutări de context .

Regiștrii CPU trebuie de asemenea să fie salvați când intervine o comutare de context deoarece ei conțin starea curentă a procesului în execuție. Aceste comutări de context nu sunt ieftine în termenii resurselor sau timpului. Pentru a le face să merite, sistemele de operare trebuie să se descurce cu ele redepe si eficient.

Este interesant de notat corelația strânsă între avansul în arhitectură și evoluția sistemelor de operare. Computerele de primă generație au folosit tuburi cu vacuum și relee și erau destul de încete. Nu era într-adevăr nevoie de un sistem de operare pentru că mașinile nu puteau face față sarcinilor multiple concomitente. Operatorii umani realizau managementul sarcinilor cerute.

Computerele de a II –a generație erau construite cu tranzistori. Aceasta a avut ca rezultat creșterea vitezei și capacității CPU.

Deși capacitatea CPU crescuse, încă era costisitoare și trebuia utilizată la maxim. Procesarea de grup a fost introdusă ca mjloc de a menține CPU ocupată. Monitoarele au ajutat la procesare, furnizând protecție minimă și facând față întreruperilor. A treia generație de calculatoare era marcată de folosirea circuitelor integrate. Aceasta, din nou a avut ca rezultat creșterea vitezei. Rularea singură nu putea ține CPU ocupat, deci s-a introdus împărțirea timpului. Memoria virtuală și multiprogramarea au necesitat un monitor mai sofisticat, care a evoluat în ceea ce noi numim un sistem de operare.

Tehnologia generației a IV – a, VLSI, a permis dezvoltarea computerelor personale. Sistemele de operare în rețea și sistemele distribuite sunt un produs al acestei tehnologii. Minimizarea circuitelor a economisit spațiu, având astfel mai mult loc pentru circuite decât o făceau țevile, procesarea cu dispozitive și multiprocesarea.

Sistemele de operare vechi erau divergente în design. Vânzătorii produceau frecvent unul sau mai multe sisteme de operare unei platforme date. Sistemele de operare de la același vânzător, concepute pentru platforme diferite putea varia radical atât în operații cât și în serviciile pe care le furnizau.

Nu era neobișnuit pentru un vânzător să introducă un nou sistem de operare atunci când un nou model de computer era introdus.

IBM a pus capăt acestei practici la mijlocul anilor 60, când a introdus seria 360 de computer. Deși fiecare computer din familia 360 de mașini era diferit cu mult ca performanță și audiență, toate computerele rulau același sistem de operare de bază, OS/360. Unix este un alt sistem de operare care exemplifică ideea unui sistem de operare care se întindea peste multe platforme hard. Ken Thompson, de la Laboratoarele AT&T, a început lucrul la Unix în 1969. La început Thompson a scris Unix în limbaj de asamblare. Pentru că limbajele de asamblare sunt specifice hardului, orice cod scris pentru o platformă trebuia să fie rescris și asamblat pentru o platformă diferită. Thompson a fost descurajat la gândul rescrierii codului său Unix pentru mașini diferite. Cu intenția de a se scuti de munca viitoare, el a creat un nou limbaj de nivel înalt numit B. S-a dovedit că B era prea încet pentru a suporta activități de sistem de operare. Dennis Ritchie s-a adăugat lui Thompson pentru a dezvolta limbajul de programare C, realizând primul compilator C în 1973. Thompson și Ritchie au rescris sistemul de operare Unix în C, pentru totdeauna, alungând credința ca sistemele de operare trebuie sa fie scrise în limbaj de asamblare. Pentru că era scris în lumbaj de nivel înalt, și putea fi compilat pentru diferite platforme, Unix era portalul. Depărtarea majoră de tradiție a permis Unix să devină extrem de popular, și, deși și-a gasit încet drumul pe piață, este sistem de operare la alegere pentru milioane de utilizatori. Neutralitatea hardului arătată de Unix permite utilizatorilor să selecteze cel mai bun hard pentru aplicațiile lor, în loc de a fi limitați la o platformă specifică. Există sute de diferite variante Unix disponibile azi, incluzând Solaris, de la Sun, AIX de la IBM, HP – UX de la Hewlett – Packard și Linux pentru PC – uri și servere sisteme de Timp Real, Mutiprocesor și Sisteme Distribuite de Rețea.

Poate cea mai mare provocare pentru designerii de sisteme de operare din ultimii ani a fost introducerea sistemelor de timp – real, multiprocesor și distribuite/de rețea. Sistemele de timp – real sunt folosite pentru controlul proceselor în manufacturarea plantelor, liniilor de asamblare, roboticii și sistemelor fizice complexe cum ar fi stația spațială, pentru a numi doar câteva. Sistemele de timp – real au constrângeri de cronometru severe. Dacă nu se întâlnesc limite de timp specifice, pot surveni stricăciuni fizice sau alte efecte indezirabile pentru persoane sau proprietați. Pentru că aceste sisteme trebuie să răspundă evenimentelor externe, este critică programarea corectă a procesului. Imaginați-vă un sistem care controlează o instalație de putere nucleară care nu ar putea răspunde destul de rapid unui semnal de alarmă a temperaturiii critice în interior.

În sistemele de timp – real hard (cu potențiale rezultate fatale dacă nu este întâlnit un ternmen limită) nu pot fi erori.

În sistemele de timp – real soft, întâlnirea termenelor limită este dezirabil, dar nu are ca rezultat catastrofe dacă se pierd termenele limită. QNX este un excelent exemplu al unui sistem de operare de timp – real. (RTOS) conceput pentru a întâlni cereri de programare strictă. QNX este de asemenea potrivit pentru sistemele încastrate, pentru că este puternic, totuși, are o mică urmă (cere memorie foarte puțină) și tinde a fi foarte sigur.

Sistemele multiprocesor prezintă propriul lor set de provocări pentru că ele au mai mult de un procesor care trebuie programat. Maniera în care sistemele de operare alocă procesele pentru procesare este o considerație majora de design tipic, într-un cadru de multiprocesoare CPU – rile cooperează unul cu altul pentru a rezolva problemele, lucrând în paralel pentru a realiza un scop comun.

Coordonarea activităților procesoarelor cere ca să existe mijloace de comunicare între ele. Cerințele de sincronizare a sistemelor determină dacă procesoarele sunt concepute folosind metode de comunicare cuplate strâns sau cuplate lejer.

Multiprocesoarele cuplate strâns împart o singură memorie centralizată, care cere ca un sistem de operare să sincronizeze cu mai mare atenție procesele pentru a asigura protecția. Acest tip de cuplare este tipic folosit pentru sistemele multipro-cesor consând în 16 sau mai puține procesoare.

Multiprocesoarele simetrice (SMP) sunt o formă populară de arhitectură cuplată strâns. Aceste sisteme au procesoare multiple care împart memoria și dispozitivele I/O. Toate procesoarele realizează aceleași funcții, cu încărcătura de procesoare distribuită în toate.

Mutiprocesoarele cuplate lejer au o memorie distribuită fizic și de asmenea sunt cunoscute ca sisteme distribuite. Sistemele distribuite pot fi văzute în două moduri diferite. O colecție distribuită de stații de lucru pe un LAN (local area network), fiecare cu sistemul său propriu de operare, se referă tipic la un sistem de rețea. Aceste sisteme sunt motivate de nevoia unor multiple computere pentru a împărți resursele.

Un sistem de operare în rețea include proviziile necesare, cum ar fi execuția cu comandă la distanță, acces la fișiere de la distanță, login de la distanță, pentru a atașa mașinile la rețea. De asemenea procesoarele utilizatorilor au capacitatea de a comunica prin rețea cu procesoarele altor mașini. Sistemele fișierelor de rețea sunt una din cele mai importante aplicații ale sistemelor de rețea. Acestea permit multiplelor mașini să împartă un sistem logic de fișiere, deși mașinile sunt localizate în diferite zone geografice, și pot avea arhitecturi diferite și sisteme de operare fără legătură. Sincronizarea în cazul acestor sisteme este un punct important, dar comunicarea este chiar mai importantă pentru că această comunicare ar putea surveni prin rețele aflate la mare distanță. Deși sistemele de rețea pot fi distribuite peste zone geografice, ele nu sunt considerate sisteme de distribuție adevărate.

Un sistem distribuit adevărat diferă de rețaua unei stații de lucru într-un mod semnificativ. Un sistem de operare distribuit rulează concomitent pe toate mașinile, prezentând utilizatorului imaginea unei singure mașini. În contrast, într-un sistem de rețea, utilizatoul este conștient de existența diferitelor mașini. Ca urmare, transparența este un punct important în sistemele distribuite. Utilizatorului nu ar trebui să i se ceară să folosească nume diferite pentru fișiere pur și simplu pentru că ele există în diferite locații, furnizează diferite comenzi pentru diferite mașini sau relizează orice altă interacțiune dependentă doar de locația mașinii.

Pentru cea mai mare parte, sistemele de operare pentru multiprocesoare nu au nevoie să difere semnificativ de acelea pentru sistemele uniprocesoare.

Programarea este, totuși, una dintre principalele diferențe pentru că CPU – urile multiple trebuie ținute ocupate. Dacă programarea nu este făcută corespunză-tor, inerentele avantaje ale paralelismului multiprocesoarelor nu sunt pe deplin relizate. În particular, dacă sistemele de operare nu furnizează uneltele corespunză-toare pentru a exploata paralelismul, performanța va suferi.

Sistemele de timp – real după cum am menționat, cer sisteme de operare special concepute. Sistemele de timp – real ca și sistemele încastrate (încorporate) cer un sistem de operare de mărime medie și utilizarea de resurse minime. Rețelele fără fir, care combină compactarea sistemelor încorporate cu punctele caracteristice sistemelor de rețea, au motivat de asemenea inovațiile în designul sistemelor de operare.

Sistemele de operare pentru calculatoarele personale

Sistemele de operare pentru PC au un scop diferit de acela pentru sistemele mai largi. În timp ce sistemele mai largi (mari) vor să furnizeze performanță excelentă si utilizarea hardului (în timp ce fac și sistemul ușor de folosit) sistemele de operare pentru PC – uri au un singur obiectiv principal: să facă utilizatorul sistemului prietenos.

Când Intel a ieșit cu microprocesorul 8080 în 1974, compania i-a cerut lui Gary Kildall să scrie un sistem de operare. Kindall a construit un controler pentru dischetă, a logat discul pe 8080 și a scris softul pentru sistemul de operare bazat pe dischetă CPM (Program de Control pentru Microprocesoare). BIOS – ul, sistemul bază input (output) a permis CPM să fie exportat pentru diferite tipuri de PC – uri pentru că furniza interacțiunile necesare cu dispozitive pentru input si output. Pentru că dispozitivele I/O sunt cele mai probabile componente care să varieze de la un sistem la altul, prin împachetarea interfețelor pentru aceste dispozitive într-un singur modul sistemele de operare actuale ar putea rămâne același pentru diferite mașini. Doar BIOS – ul trebuie să fie schimbat.

Intel a presupus în mod greșit că mașinile bazate pe discuri aveau un viitor întunecat. După de a decis să nu folosească acest nou sistem de operare, Intel i-a dat lui Kildall drepturile pentru CPM. În 1980, IBM a avut nevoie de un sistem de operare pentru PC – ul IBM. Deși IBM l-a abordat mai întâi pe Kildall, afacerea a sfârșit prin a merge la Microsoft, care cumpărase un sistem de operare bazat pe disc numit QDOS (sistem de operare rapid și murdar) de la compania de produse pentru computer din Seattle pentru 15000 $.

Softul a fost denumit MS – DOS, iar restul este istorie.

Sistemele de operare ale vechilor computere personale operau cu comenzi tipărite de la tastatură. Alan Key, inventator al GUI (interfața utilizatorului grafic) și Doug Engelbart, inventatorul mouse – ului, ambii de la centrul de cercetare Xerox Palo Alto, au schimbat pentru totdeauna fața sistemelor de operare, atunci când ideile lor au fost încorporate în sistemele de operare. Prin eforturile lor cuvintele lor comandă au fost înlocuite de ferestre, icoane și meniuri drop – down (scăpat jos). Microsoft a popularizat aceste idei (dar nu le-a inventat) prin seria sa de sisteme de operare Windows: windows 1.x, 2.x, 2.x, 95, 98, ME, NT 2000 și XP. Sistemul de operare grafic Macintosh, Mac OS, care a precedat windows GUI timp de câțiva ani, a mers de asemenea prin numeroase versiuni.

Unix câștigă popularitate în lumea computerelor personale prin Linux și Open BSD. Există multe alte sisteme de operare pe bază de disc (cum ar fi DR Dos, PC Dos, și OS/2), dar nici unul nu este atât de popular ca windows și numeroasele variante ale lui Unix.

8.2.2. Designul sistemelor de operare

Deoarece singura piesă de soft mai importantă folosită de un computer este sistemul său de operare, o grijă specială trebuie avută la designul său. Sistemul de operare controlează funcțiile de bază ale computerului incluzând managementul memoriei și I/O, pentru a nu mai aminti de interfața “privește și simți”. Un sistem de operare diferă de majoritatea altor softuri prin aceea că este condus de eveniment, însemnând că el realizează sarcini ca răspuns la comenzi, programe de aplicații, dispozitive I/O și întrerupe.

Patru factori principali conduc designul sistemelor de operare: performanță, putere, cost și compatibilitate. Până acum, ar trebui să aveți o imagine a ceea ce este un sistem de operare, dar sunt multe imagini diferite asupra a ceea ce ar trebui să fie un sistem de operare, așa cum este evidențiat de diferite sisteme de operare disponibile astăzi. Majoritatea sistemelor de operare au interfețe similare, dar variază mult în modul în care sunt îndeplinite sarcinile. Unele sisteme de operare sunt minimaliste în design, alegând să acopere doar funcțiile cele mai de bază, în timp ce altele încearcă să includă fiecare caracteristică ce poate fi concepută.

Unele au interfețe superioare, dar au lipsuri în alte zone, în timp ce altele sunt superioare în managementul memoriei și al I/O, dar au lipsuri în aria prieteniei utiliuatorului. Nici un sistem de operare nu e superior din toate punctele de vedere. Două componente sunt cruciale în designul sistemelor de operare: nucleul și programele sistemului. Nucleul este inima sistemelor de operare. El este folosit de managerul de proces, de programator, de mangerul de resurse și de managerul de I/O. Nucleul este resonsabil pentru programarea, sincronizarea, securitatea, managementul memoriei și rezolvarea întreruperilor. El are un prim control al hardului de sistem, incluzând întreruperile, regiștrii de control, cuvintele status si cronometru. El încarcă toate driverele dispozitivelor, furnizează utilități comune și coordonează toată activitatea I/O. Nucleul trebuie să cunoască specificurile hardului pentru a combina toate aceste piese într-un sistem funcțional.

Cele două extreme ale designului nucleului sunt arhutecturile micronucleelor și nucleele monolitice. Micronucleele furnizează funcționalitatea sistemului de operare rudimentar, bazându-se pe alte module să realizeze sarcini specifice, mișcând astfel multe servicii ale sistemului de operare în spațiul utilizatorului. Aceasta permite multor servicii să fie restaurate sau reconfigurate fără restartarea întregului sistem de operare. Micronucleele furnizează securitate,deoarece serviciile care rulează la nivelul utilizatorului au acces restrâns la resursele sistemului. Micronucleele pot fi comandate și prezentate altor harduri mai ușor decât nucleele monolitice. Totuși, comunicarea adițională între nucleu și alte module este necesară, adesea având ca rezultat un sistem mai încet și mai puțin eficient.

Trăsăturile cheie ale designului micronucleului sunt mărimea sa mai mică, portabilitate ușoară, și aria de servicii care rulează un strat deasupra de nucleu în locul nucleului însuși.

Dezvoltarea micronucleului a fost semnificativ încurajată de creșerea în SMP și alte sisteme de microprocesoare. Exemple de sisteme de operare de nucleu include Windows 2000, Mach și QNX.

Nucleele monolitice furnizează toată funcționalitatea lor esențială printr-un singur proces. În consecință, ele sunt semnificativ mai mari decât micronucleele. Concepute tipic pentru anumite harduri, nucleele monolitice interacționează direct cu hardul, deci pot fi optimizate mai ușor decât sistemul de operare micronucleu. Din acest motiv nucleele monolitice nu sunt ușor portabile. Exemple de sisteme de operare de nucleu monolitice includ Linux, Mac OS și DOS.

Pentru că un sistem de operare consumă resurse în plus față de managerierea lui, designerii trebuie să ia în considerare mărimea produsului finit. De exemplu, Solaris de la Sun Microsystem cere 8 MB de spațiu pe disc pentru o instalare completă. Windows 2000 care cam de două ori aceeași cantitate. Aceste statistici atestă explozia funcționalității sistemelor de operare de-a lungul ultimelor 2 decade. MS – DOS 1.0 se potrivește confortabil pe o singură dischetă de 100 KB.

8.2.3. Serviciile sistemelor de operare.

De-alungul precedentei discuții despre arhitectura sistemului de operare am menționat câteva dintre cele mai importante servicii pe care sistemele de operare le furnizează. Sistemele de operare supraveghează toate sarcinile critice ale managementului de sistem, managementul memoriei, managementul procesorului, protecția și interacțiunea cu dispozitivele I/O. în rolul său ca interfață, sistemul de operare determină cum interacționează utilizatorul cu computerul, servind ca tampon între utilizator și hard. Fiecare din aceste funcțiuni este un factor important în determinarea utilizaeilității și performanței generale a sistemului. De fapt, uneori acceptăm o performanță redusă dacă sistemul e ușor de folosit. Nicăieri nu este acest târg mai vizibil decât în zona interfețelor grafice.

Interfața umană

Sistemele de operare furnizează un strat de abstracție între utilizator și hardul mașinii. Nici utilizatorii, nici aplicațiile nu văd hardul direct deoarece sistemele de operare furnizează o interfață pentru a ascunde detaliile mașinii. Sistemele de operare furnizează trei interfețe de bază, fiecare furnizând o vedere diferită pentru un anumit element. Cei care dezvoltă hardurile sunt interesați de sistemele de operare ca interfață pentru hard. Cei care dezvoltă aplicații văd sistemele de operare ca o interfață la variate programe și servicii. Utilizatorii obișnuiți sunt interesați mai mult în interfața grafică, care este interfața cea mai comun asociată cu termenul interfață.

Interfețele sistemelor de operare pentru utilizatori pot fi divizate în 2 categorii generale: interfețe pentru liniile de comandă și interfețe pentru utilizatorii grafici (GUI). Interfețele pentru liniile de comandă, oferă o replică la care utilizatorul introduce diferite comenzi, incluzându-le pe cele pentru copierea fișierelor, ștergerea fișierelor, oferind o listare a directorului și manipulând structura directorului. Interfețele pentru linii de comandă cer utilizatorului să cunoască sintaxa sistemului, care este adesea prea complicată pentru utilizatorul mediu.

Totuși, pentru aceia care stăpânesc un anumit vocabular de comandă, sarcini

le sunt îndeplinite mai eficient cu comenzi directe spre deosebire de utilizarea unei interfețe grafice. GUI, pe de altă parte, oferă o interfață mai accesibilă pentru utilizatorul ocazional. GUI moderne constau în ferestre plasate pe desktopuri. Ele includ caracteristici cum ar fi icoane și alte reprezentări grafice ale fișierelor care sunt manipulate folosind un mouse. Exemple de interfețe pentru liniile de comandă includ carcasele Unix și Dos. Exemple de GUI includ diferitele variante ale Microsoft Windows și MACOS. Costul care scade al echipamentului, în special procesoare și memorie, a făcut practică adăugarea GUI la multe alte sisteme de operare. De un interes particular este Windows X, echipat cu multe sisteme de operare Unix.

Interfața utilizatorului este un program sau un set mic de programe care constituie managerul display – ului. Acest modul este în mod normal separat de funcțiunile sistemului de operare central găsit în nucleul sistemului de operare. Majoritatea sistemelor de operare moderne creează un pachet global de sisteme de operare cu module pentru intefață, fișiere de comandă care sunt strâns legate de nucleu. Maniera în care aceste module sunt legate unele cu altele este o caracteristică definitorie a sistemelor de operare de astăzi.

Managementul procesului

Managementul procesului stă la baza serviciilor sistemelor de operare. El include începând de la crearea proceselor (instalând structurile corespunzătoare pentru a stoca informația despre fiecare), până la programarea utilizării diferitelor resurse de către procese și până la ștergerea proceselor și curățare după terminarea lor. Sistemele de operare păstrează urmele fuecărui proces, statutul său (care include valorile variabilelor, conținutul regiștrilor CPU, precum și starea de fapt – în rulare, gata sau în așeptare – a procesului), resursele pe care le folosește și acelea pe care le cere. Sistemul de operare menține un ochi care privește activitățile fiecărui proces pentru a preveni problemele de sincronizare, care se ridică atunci când procese concurente au acces la resurse care se pot împărți. Aceste procese trebuie să fie monitorizate atent pentru a evita inconsistențele din date și interferen-țele accidentale.

La orice moment dat, nucleul manageriază o colecție de procese, consând în procesele utilizatorului și procesele sistemului. Cele mai multe procese sunt independente unul de altul. Totuși, în eventualitatea că e nevoie ca ele să interacționeze pentru a atinge un scop comun, se bazează pe un sistem de operare pentru a facilita sarcinile de comunicare între procese.

Programarea proceselor este o parte largă a rutinei normale a sistemelor de operare. Mai întâi sistemele de operare trebuie să determine care procese să fie admise la sistem (numite adesea programe pe termen lung). Apoi trebuie să determine cărui proces i se acordă CPU la orice moment dat (programare pe termen scurt). Pentru a realiza programarea pe termen scurt, sistemele de operare mențin o listă de procese pregătite, astfel încât poate face diferența între procesele care așteaptă resursele și acelea care sunt programate și rulează. Dacă un proces în derulare are nevoie de I/O sau alte resurse, el renunță voluntar la CPU și se autodeplasează pe o listă de așteptare, iar un alt proces este programat pentru execuție. Această secvență de evenimente constituie o comutare de context.

În timpul unei comutări de context, toată informația pertinentă despre procesul de executare curent este salvată astfel încât, când acel proces reia execuția, el poate fi reluat exact în aceeași stare în care a fost întrerupt. Informația salvată în timpul unei comutări de context include conținuturile tururor regiștrilor CPU, tabelele de pagini și altă informație asociată cu memoria virtuală. Odată ce această informație este pliată în mod sigur, un proces întrerupt anterior (acela care se pregătește să folosească CPU) este reluat exact în aceeași stare anterioară întreruperii sale. (Procesele noi, desigur nu au o stare anterioară de reluat). Un proces poate renunța la CPU în două feluri:

În programarea neprioritară, un proces renunță la CPU în mod voluntar (posibil deoarece are nevoie de altă resursă neprogramată). Totuși, dacă sistemul este instalat cu împărțirea timpului, procesul ar putea fi luat dintr-o stare de rulare și plasat într-o stare de acceptare de către sistemele de operare. Aceasta este numită planificare prioritară pentru că procesul este prioritar, iar CPU este îndepărtat.

Prioritatea apare de asemenea când procesele sunt planificate și întrerupte conform priorității. De exemplu dacă un proces de prioritate scăzută rulează și un proces de mare prioritate are nevoie de CPU, lucrarea de prioritate scăzută este plasată într-o coadă pregătită (se realizează o comutare de context), permițând lucrării de înaltă prioritate să ruleze imediat.

Principala sarcină a sistemelor de operare în planificarea proceselor, este să determine care proces ar trebui să fie următorul pentru CPU. Factorii care includ deciziile de planificare includ planificarea CPU „cererea”, timpul de răspuns, timpul de așteptare și timpul de răspuns. Planificarea de termen scurt poate fi făcută în mai multe feluri. Abordările includ primul – venit, primul – servit (FCFS), cea mai scurtă lucrare mai întâi (SJF) și planificarea prioritară.

În planificarea primul venit – primul servit procesele sunt alocate resurselor de procesor în ordinea în care sunt cerute. Se renunță la controlul CPU când procesul în executare s-a terminat. Planificarea FCFS este un algoritm neprioritar care are avantajul de a fi ușor de implementat. Totuși, este nepotrivit pentru sistemele care suportă utilizatori multipli pentru că există o variație mare a timpului mediu în care un proces trebuie să aștepte să folosească CPU. În plus, un proces poate monopoliza CPU, cauzând întârzieri în executarea altor procese.

În planificarea mai întâi a celei mai scurte lucrări, procesul cu cel mai scurt timp de execuție are prioritate asupra tuturor celorlalte din sistem SJF este un algoritm de planificare optim.

Principala problemă este ca nu există cale de a ști în avans exact cât de mult va rula o lucrare lungă. Sistemele care angajează cea mai scurtă lucrare mai întâi, aplică o anumită euristică în a face estimări asupra timpului de rulare a lucrării, dar aceste euristici sunt departe de a fi perfecte. Cea mai scurtă slujbă poate fi nepriotitară sau prioritară. (vesriunea prioritară este adesea numită cel mai scurt timp rămas mai întâi).

Planificarea cererii – este o schemă de planificare prioritară simplă, și echitabilă. Fiecărui proces îi este alocată o anumită parte din timpul CPU. Dacă procesul încă rulează când îi expiră timpul său este comutat printr-o comutare de context. Următorului proces care așteaptă la rând îi este acordată partea sa din timpul CPU. Planificarea cererii este folosită în sistemul de împărțire a timpului. Când planificatorul angajează bucăți de timp suficient de mici, utilizatorii nu sunt conștienți că împart resursele sistemului. Totuși, bucățile de timp nu ar trebui să fie atât de mici pentru că timpul comutării de context este mare prin comparație.

Planificarea prioritară asociază o prioritate fiecărui proces. Când planificato-rul de timp scurt selectează un proces din coada pregătită, este ales procesul cu cea mai mare prioritate.FCFS dă egală priotitate tuturor proceselor. Cea mai importan-tă problemă cu planificarea prioritară este potențialul de distrugere, sau blocarea indefinită. Vă puteți imagina ce frustrant ar fi să încerci să reulezi o lucrare mare pe un sistem ocupat, când utilizatorii angjează lucrări mai scurte care rulează înaintea programului tău. Folclorul spune că atunci când o structură principală dintr-o mare universitate a fost oprită, s-a găsit o lucrare la o coadă pregătită care încerca să ruleue de ani de zile!

Unele sisteme de operare oferă o combinație de abordări ale programării. De exemplu, un sistem ar putea folosi un algoritm prioritar, bazat pe prioritate, primul – venit, primul – servit. Sistemele de operare foarte complexe care suportă sisteme de clasă antreprize permit un anume grad de control al utilizatorului asupra duratei împărțirii timpului, numărului de sarcini concurente permise și alocarea priorităților la diferite clase de lucrări.

Multisarcinile (permițând proceselor multiple să ruleze în același timp) și multifirele (permițând unui proces să fie divizat în diferite fire de control) oferă provocări interesante pentru planificarea CPU. Un fir este cea mai mică unitate planificabilă într-un sistem. Firele împart același cadru de execuție ca și procesul lor părinte, incluzând regiștrii săi CPU și tabla de pagini. Datorită acestui lucru comutarea de context printre fire generează mai puține cheltuieli, deci ei pot să survină mult mai rapid decât o comutare de context implicând întregul proces. Depinzând de gradul de concurență cerut, este posibil să ai un proces cu un fir, un proces cu fire multiple, procese cu multiple fire singure sau procese cu multiple multifire. Un sistem de operare care suportă multifirele trebuie să fie capabil să facă față tuturor combinatiilor.

Managementul resurselor

În plus față de managementul proceselor, sistemele de operare manageriauă resursele sistemului. Pentru că aceste resurse sunt relativ scumpe este preferabil să le permiți să fie împărțite. De exemplu multiple procese pot împărți un procesor, multiple programe pot împărți memorie fizică, și multipli utilizatori și fișiere pot împărți un disc. Există 3 resurse de cate sistemele de operare trebuie să aibă o grijă specială: CPU, memoria și I/O. Accesul la CPU este controlat de planificator. Memoria și accesul I/O cere un set diferit de controale și funcțiuni.

Amintiți-vă din capitolul 6 că majoritatea sistemelor moderne au un anumit tip de memorie virtuală care extinde RAM (Random Access Memory). Aceasta implică faptul că părți ale câtorva programe pot coexista în memorie și fiecare proces trebuie să aibă o tabelă de pagini. La început, înainte ca sistemele de operare să fie concepute pentru a se descurca cu memoria virtuală;programatorul implementa memora virtuală folosind o schemă de acoperire. Dacă un program era prea mare pentru a se potrivi în memorie, programatorul l-a divizat în bucăți, încărcând doar datele și instrucțiunile necesare pentru a rula la un anumit moment. Dacă era nevoie de date sau instrucțiuni, depindea de programator să se asigure că piesele corecte sunt în memorie. Programatorul era responsabil pentru managerie-rea memoriei. Acum sistemele de operare au depășit această muncă.

Sistemele de operare translatează adresele virtuale în adrese fizice, transformă paginile la si de la disc și menține tabelele de pagini de memorie. De asemenea sistemele de operare determină alocarea memoriei principale și realizează urmele structurilor libere. Pentru ca dezalocă spațiul de memorie, sistemul de operare realizează „colactarea gunoiului”, care este procesul contopirii micilor porțiuni de memorie liberă în bucăți mai utilizabile. În plus, față de procesele de împărțire a unei singure memorii finite, ele împart de asemenea dispozitive I/O. Majoritatea inputului si outputului este făcut la cererea unei aplicații.

Sistemul de operare furnizează serviciile necesare pentru a permite inputul și pentru a apăra outputul. Este posibil pentru aplicații să aibă propriul lor I/O, fără să folosească sistemul de operare, dar în plus față de duplicarea efortului, aceasta prezintă protecție si surse de acces. Dacă unele procese diferite încearcă să folosească același dispozitiv I/O simultan, cererile trebuie să fie mediate. Sistemul de operare este cel care realizează această sarcină. Sistemul de operare oferă o interfață generică la I/O prin variate chemări ale sistemului. Aceste chemări permit unei aplicații să ceară un serviciu I/O prin sistemul de operare. Sistemul de operare cheamă apoi driverele dispozitivului care conțin soft implementând un set standard de funcțiuni relevante pentru mecanismele I/O. Sistemul de operare de asemenea manageriază fișierele discului. Sistemul de operare are grijă de crearea de fișiere, ștergerea de fișiere, crearea de directoare și ștergerea directoarelor și de asemenea furnizează suport pentru primitivele care manipulează fișierele și directoarele și plasarea lor pe dispozitive de stocare secundare.

Deși driverele dispozitivelor au grijă de multe din detaliile particulare, sistemul de operare coordonează activitățilr driverelor dispozitivelor care suportă funcțiile sistemelor de I/O.

Securitate și protecție

În rolul său ca resursă și manager de procese, sistemul de operare trebuie să fie sigur că totul lucrează corect, cinstit și eficient. Împărțirea resurselor toutși, creează o multitudine de expuneri cum ar fi potențialul de acces neautorizat sau modificarea datelor. Ca urmare sistemul de operare servește de asemenea ca protector de resurse, fiind sigur că „baieții răi” nu strică lucrurile pentru nimeni altcineva.

Procesele concurente trebuie protejate unul de altul și procesele sistemelor de operare trebuie să fie protejate de toate procesele utilizatorilor. Fără această protecție, un program al unui utilizator ar putea să șteargă codul sistemului de operare. Sistemul cu utilizatori multipli cer servicii de securitate adiționale pentru a proteja atât resursele împărțite (cum ar fi memoria și dispozitivele I/O) și resursele neîmpărțite (cum ar fi fișierele personale). Protecția memoriei păzește împotriva unui bug în programul unui utilizator afectând alte programe sau un program malițios care să ia controlul asupra întregului sistem. Protecția CPU asigură că programele utilizatorilor nu se blochează în cercuri infinite consumând ciclurile CPU necesare altor lucrari.

Sistemele de operare oferă servicii de securitate într-o varietate de moduri. Mai întâi procesele active sunt limitate ca execuție în interiorul spațiului propriei memorii. Toate cererile pentru I/O sau alte resurse din trecerea procesului prin sistemele de operare, care apoi procesează cererea. Sistemele de operare execută majoritatea comenzilor în modul utilizatorului și altele în modul nucleului. În acest fel, resursele sunt protejate împotriva utilizării neautorizate. Sistemele de operare de asemenea oferă facilități de control al accesului utilizatorului, tipic prin nume de intrare și parole. O protecție mai puternică poate fi afectată de restricționarea proceselor la un singur subsistem sau partiție.

8.3. Medii protejate

Pentru a oferi protecție sistemele de operare cu multiutilizatori păzesc împotriva proceselor care rulează nebunește în sistem. Execuția proceselor trebuie să fie izolată atât de sistemele de operare cât și de alte procese. Accesul la resursele care se împart trebuie să fie controlat și mediat pentru a evita conflictele. Există un număr de moduri în care se pot ridica bariere protectoare într-un sistem. În această secțiune noi examinăm 3 dintre ele: mașini virtuale, subsisteme și partiții.

8.3.1. Mașini virtuale

Sistemele de împarțire a timpului din anii 1950 – 1960 s-au luptat mereu cu probleme referitoare la resursele împărțite cum ar fi: memoria, depozitarea magnetică, cititorii de carduri, tipăritorii și ciclurile procesoare.

Hardul acestei ere nu putea suporta soluțiile care erau în mintea multor oamnei de știință care se ocupau de computere. Într-o lume mai bună, fiecare proces de utilizator ar avea mașina sa proprie, o mașină imaginară care ar putea coexista în pace cu multe alte mașini imaginare în interiorul mașinii reale.

În ultima parte a anilor 1960 și prima parte a anilor 1970, hardul devenise în cele din urmă suficient de sofisticat pentru a da aceste „mașini virtuale” compute-relor folosite în scop general.

Mașinile virtuale sunt simple ca și concept. Hardul real al computerului real este sub comanda exclusivă a unui program de control (sau nucleu). Programul de control creează un număr arbitrar de mașini virtuale care execută sub nucleu ca și cum ar fi procese obișnuite de utilizator, subiect al acelorași restricții ca orice program care rulează în spațiul utilizatorului. Programul de control prezintă fiecare mașină virtuală cu o imagine care seamănă cu hardul mașinii reale. Fieacre mașină virtuală „vede” apoi un mediu constând într-un CPU, regiștrii, dispozitive I/O și memorie (virtuală), deși aceste resurse au fost dedicate utilizării exclusive a mașinii virtuale. Astfel, mașinile virtuale sunt mașini imaginare reflectând resursele sistemelor pe deplin maturizate. Așa cum este ilustrat în fig. 8.1, un program utilizator care se execută între limitele mașinii virtuale poate accesa orice resursă de sistem care este definită. Când un program invocă un serviciu de sistem să scrie datele pe un disc, de expemplu el execută aceeași chemare pe care ar executa-o dacă ar rula pe o mașină reală. Mașina virtuală primește cererea I/O și o pasează programului de control pentru execuția pe hardul adevărat.

Fig. 8.1 Imaginile mașinii virtuale lucrând sub un program control

Este posibil în întregime pentru o mașina virtuală să ruleze un sistem de operare care diferă de sistemul de operare al nucleului. Este de asemenea posibil pentru fiecare mașină virtuală să ruleze un sistem de operare care este diferit de sistemele de operare rulate de alte mașini virtuale din sistem. De fapt acesta este cazul cel mai des întâlnit. Daca a-ti deschis vreodată o comandă MS – DOS pe un windows (de la 95 până la XP) a-ti inițiat un mediu al unei mașini virtuale. Programul de control pentru aceste versiuni Windows este numit un manager al unei mașini virtuale windows (VMM). VMM – ul este un subsistem în mod protejat de 32 bitți (vezi urmatoarea secțiune) care creează, rulează, monitorizează și termină mașinile virtuale. VMM – ul este încărcat în memorie în momentul boot – ului. Când este invocat prin interfața unei comenzi, VMM – ul crează o mașină “MS – DOS ” care rulează sub o imagine virtuală a unui procesor Intel 8086/8088 de 16 biți. Deși sistemul real are mult mai mulți regiștrii (care sunt de 32 biți), sarcinile care se execută sub DOS văd doar numărul limitat de regiștrii de 16 biți carecateristici unui procesor 8086/8088. Programul care controlează VMM convertește instrucțiunile de 16 biți în instrucțiuni de 32 biți înainte să fie executate pe procesorul sistemului real. La întreruperile hardului de serviciu, VMM încarcă un set definit de drivere de dispozitive virtuale (VxDs) de câte ori este bootat în windows. Un VxD poate simula hardul extern sau poate simula o interfață de programare accesată prin instrucțiuni privilegiate. VMM – ul creează biblioteci cu link – uri dinamice în mod protejat de 32 biți (explicate în secțiunea 8.4.2) permițând dispozitivelor virtuale să intercepteze întreruperile și greșelile. În acest fel el controlează accesul unei aplicații la dispozitivele hardului și softului de sistem.

Desigur mașinile virtuale folosesc memorie virtuală, care trebuie să coexiste cu memoria sistemului de operare și cu alte mașini virtuale care rulează un sistem. O diagramă a alocării adreselor de memorie a Windows 95 este arătată în fig. 8.2. fiecărui proces îi este dat între 1 MB și 1 GB de spațiu privat de adresă. Acest spațiu privat de adresă este inaccesibil pentru alte procese. Dacă un proces neautorizat încearcă să folosească memoria protejată a unui alt proces sau a unui sistem de operare, apare o greșală de protecție (anunțată brutal printr-un mesaj pe un ecran simplu albastru). Regiunea de împărțire a memoriei permite împărțirea de date și coduri de program în timpul proceselor Regiunea superioară menține componentele mașinii virtuale de sistem în plus față de DLL – uri accesibile tuturor proceselor. Regiunea inferioară nu este adresabilă ceea ce servește ca un mod de detectare a erorilor indicator.

Fig. 8.2 Harta de memorie pentru Windows 95

Când modelele virtuale suportă mașini virtuale, ele sunt capabile mai bine să ofere protecția, securitatea și manageabilitatea cerute de componentele de clasă largă. Mașinile virtuale de asemenea oferă compatibilitate pe platforme nenumăra-te de hard. O asemenea mașină, Mașina Virtuală Java este descrisă în secțiunea 8.5

8.3.2. Subsisteme și Partiții

VMM – ul windowsului este un subsistem care începe când este boot – at windows – ul. De asemenea Windows – ul pornește alte subsisteme cu scop special pentru managementul fișierelor, I/O și managementul configurațiilor. Subsistemele stabilesc medii logic distincte care pot fi configurate individual. Subsistemele rulează la vârful nucleului sistemelor de operare, care le oferă acces la resursele sistemului fundamental, cum ar fi planificatorul CPU, care trebuie să fie împărțit între câteva subsisteme.

Fiecare subsistem trebuie să fie definit în contextul sistemului de control. Aceste definiții includ descrieri de resursă cum ar fi fișierele disc, cozi de input și output și diferite alte componente de hard cum ar fi sesiuni de terminal și tipăritori. Resursele definite unui subsistem nu sunt întotdeauna văzute direct de către nucleul de dedesupt, dar sunt vizibile prin subsistemul pentru care sunt definite. Resursele definite unui subsistem pot sau nu pot fi împărțite între subsitemele egale.

Fig. 8.3: O singură resursă poate fi definită la sisteme multiple

Subsistemele participă la managementul activităților sistemelor computere-lor mari și foarte complexe. Pentru că fiecare subsistem este propria sa entitate controlabilă discret, administratorii de sisteme pot porni și opri fiecare subsistem individual, fără să deranjeze nu cleul sau orice alte subsisteme care se întâmplă să ruleze. Fiecare subsistem poate fi transformat individual prin realocarea resurselor sistemului, cum ar fi adăugarea sau îndepărtarea spațiului discului sau memoriei. Mai mult, dacă un proces scapă de sub control în interiorul unui subsistem – sau clachează subsistemul însuși – de obicei este afectat doar subsistemul în care ruleează procesul. Astfel, subsistemele nu doar că au fost sistemele mai manageri-abile, dar de asemenea le fac mai robuste.

În sisteme foarte mari de computere, subsistemele nu merge destul de depar-te în segmentarea mașinii și a resurselor sale. Uneori o barieră mai sofisticată se cere pentru a facilita securitatea și managementul resurselor. În aceste circumstanțe un sistem poate fi împărțit în partiții logice, uneori numite LPAR, așa cum sunt ilustrate în fig. 8.4.

LPAR – urile creează mașini distincte în interiorul unui sistem fizic, cu nimic împărțit în mod implicit înre ele. Resursele unei partiții nu mai sunt accesibi-le unei alte partiții dacă partițiile rulau pe sisteme fizice separate. De exemplu dacă un sistem are două partiții A și B, partiția A poate citi un fișier din partiția B doar dacă ambele partiții sunt sunt de acord să stabilească o resursă împărțită în comun, cum ar fi un cablu sau o coadă mesaj. În general vorbind, fișierele pot fi copiate între partiții doar prin folosirea unui protocol de transfer de fișier sau a unei unități scrise în acest scop de către vânzătorul de sistem.

Fig. 8.4. Partițiile logice și sistemele lor de control: resursele nu pot fi împărțite ușor între partiții

Partițiile logice sunt în special folositoare în crearea mediilor “cutie de nisip” pentru trainingul utilizatorului sau testarea noilor programe. Mediile cutiilor de nisip își au numele din ideea că oricine care utilizează aceste medii este liber să “joace” (să se “învârtă”) în conțiuntul său, atât timp cât acest “joc” se face în interiorul limitelor cutiei de nisip. Mediile cutiilor de nisip plsează liniile stricte asupra accesibilității resurselor sistemului. Procesele care rulează într-o partiție niciodată nu pot accesa intenționat sau din inadvertență date sau procese existente în alte partiții. Partițiile cresc astfel nivelul securității într-un sistem prin izolarea resurselor de procesele care nu au voie să le folosească.

Deși subsistemele și partițiile sunt diferite unele de altele în modul în care își definesc resursele constituente, ne putem gândi la ambele ca fiind mini – modele ale arhitecturii stratificate de sistem a sistemului unui computer. În cazul unui mediu partiționat, nivelele ar putea arăta ca torturi stratificate adiacent, extinzându-se de la nivelul hardului la nivelul aplicațiilor. Subsistemele, pe de altă parte, nu sunt atât de diferite unele de altele, cu majoritatea diferențelor la nivelul softului de sistem.

8.3.3 Medii protejate și evoluția arhitecturilor sistemelor.

Până recent, mașinile virtuale, subsistemele și partițiile partițiile logice au fost considerate artefacte ale sistemelor cu structură principală “de veche tehnolo-gie”. În anii 1990 se credea că mașinile mai mici costă mai mult decât sistemele structură principală (mainframe). Paradigma “client – server ” se credea a fi mai prietenoasă cu utilizatorul și responsabilă de condițiile afacerilor dinamice. Dezvoltarea aplicațiilor pentru sistemele mici cerea rapid talent pentru programare. Programele automate de birou, cum ar fi procesarea de cuvinte sau managementul calendarului și-au gasit locații care sunt mul mai confortabile în mediile colabora-tive de rețea, având ca suport servere cu fișiere mici. Serverele tipar controlau imprimantele laser cu acces la rețea care produceau un rezultat curat pe hârtie simplă mai repede decât imprimantele de linie mainframe care puteau produce rezultate pătate pe forme speciale. Desktop – urile și platformele server mici oferă putere de calcul și avantaj la o fracție a costului puterii de calcul brute mainframe echivalente. Puterea de calcul brută, totuși, este doar o parte a unui sistem de calcul enterprise.

Când automatizarea de birou s-a mutat pe desktop, rețelele de birou au fost construite pentru a conecta sistemele desktop unele cu altele și cu serverele fișier care erau depozite pentru documente și alte lucruri vitale. Serverele aplicație găzduiau programe care realizau funcții de management al afacerilor interne. Când companiile au avut acces la Internet, s-au adăugat servere de e – mail la rețea. Dacă unul dintre servere devenea supraîncărcat cu activitate, simpla soluție era să adauge un alt server pentru a distribui încăecătura. Până la sfârsitul anilor 1990, marile întreprinderi erau proprietarii a uriașe “ferme de servere” care suportau sute de servere individuale în interiorul facilităților sigure controlate din punct de vedere al mediului.

Fermele de servere au devenit în curând consumatori vorace de putere umană, fiecare server cerând ocazional atenție considerabilă conținutul fiecărui server trebuia să fie pus pe bandă, iar benzile erau ulterior rotite offside pentru securitate. Fiecare potențial era o sursă potențială de eșec, cu diagnoze problemă și aplicații de reparare a softului devenind sarcini zilnice. A devenit evident că sistemele mai mici și mai ieftine nu erau chiar târgul (afacerea) care se credea că era mai demult. Acest lucru este adevărat în particular pentru anteprizele care se găsesc în poziția de a suporta sute de sisteme de servere mici.

Fiecare producător major de computere antrepriză oferă acum un produs de consolidare a serverului. Vânzători diferiți abordează diferit problema. Una dintre cele mai interesante este ideea creării partițiilor logice care conțin numeroase mașini virtuale în interiorul unui singur computer mare. Multele avantaje ale consolidării serverului includ:

Managerierea unui sistem mare este mai ușoară decât managerierea unei multitudini de sisteme mici;

Un singur sistem mare consumă mai puțină electricitate decât un grup de sisteme mai mici având putere de calcul echivalentă;

Cu utilizare mai puțină a puterii electrice, este generată mai puțină căldură, care economisește aerul condiționat;

Sistemele mai mari pot avea un eșec mult mai mare în ceea ce privește protecția (procesoare și discuri de rezervă sunt adesea inclse în sisteme);

Un sistem sigue este mai ușor de recuperat;

Sistemele singure ocupă mai puțin spațiu, reducând cheltuielile cu proprietățile;

Taxele pentru licența softului pot fi mai scăzute pentru un sistem singur mai mare decât pentru un număr mare de sisteme mai mici.

Se implică mai puțină muncă în aplicarea sistemului și upgradarea softului programelor utilizator pentru un sistem decât pentru multe.

Vânzătorii de sisteme mari, cum ar fi IBM, Unisys și Hewlett – Packard (pentru a numi câteva) au fost rapizi în a ataca oportunitățile de consolidare a serverelor. Structura principală (mainframe) a IBM și linia medie au fost remodelate ca Servere eSerie. Mainframe – ul Sistem/390 a fost refăcut ca Server zSerie. Serverele zSerie pot suporta 32 partiții logice.

Fiecare partiție care rulează sistemele de operare IBM Mașina Virtuală (VM) poate definii mii de sisteme Linux virtuale. Fig. 8.5 arată un model cu configurația zSerie/Linux. Fiecare sistem Linux virtual este egal capabil să susțină aplicațiile antrepriză și activitățile de comerț electronic ca un sistem Linux de sine stătător, dar fără managementul costurilor. Astfel, o fermă server de mărimea unui teren de fotbal poate fi înlocuit de o “cuite” zSerie care este puțin mai mare ca un frigider de cast. S-ar putea spune că mișcarea de consolidarea serverului condensează (rezumă) evoluția sistemelor de operare. Fabricanții de sisteme, aplicând resursele în dezvoltare ale mașinii, continuă să facă sistemele lor mai ușor de utilizat chiar și pe măsură ce ele devin din ce în ce mai puternice.

Fig. 8.5: Mașinile Linux în interiorul partițiilor logice ale unui Server zSerie IBM

8.4. Unelte de programare.

Sistemele de operare și colecția sa de aplicații oferă o interfață între utilizator, care scrie programele și sistemul care le rulează. Alte utilități, sau unelte de programare sunt necesare pentru a îndeplini mai multe aspecte mecanice ale creației softului. Le discutăm în secțiunile de mai jos.

8.4.1. Asamblorii și asamblarea.

În arhitectura noastră stratificată de sistem, nivelul care stă direct pe stratul sistemului de operare este stratul limbajului de asamblare. În capitolul 4 am prezentat o arhitectură simplă, ipotetică de mașină, pe care am nimit-o MARIE. Această arhitectură e atât de simplă, de fapt, încât nici o mașină reală nu ar folosi – o vreodata. Pentru un singur lucru, nevoia continuă de a aduce Operanzi din memorie ar face sisteme foarte încet. Sistemele reale, minimizează aducerile de memoeie oferind un număr suficient de regiștrii on – chip adresabili. Mai mult, arhitectura setului de instrucțiuni al oricărui sistem real ar fi mult mai bogată decât arhitectura lui MARIE. Multe microprocesoare au mai mult de 1000 de instrucțiuni diferite în repertoarul lor.

Deși mașina pe care am prezentat-o este destul de diferită de o mașimă reală, procesul de asamblare pe care l-am descris nu este virtual, fiecare asablator în folosință astăzi trece de 2 ori prin codul sursei. Prima trecere asamblează cât de mult cod poate în timp ce construiește o tabelă de simboluri; a doua trecere completează instrucțiunile binare folosind valorile adreselor recuperate din tabela de simboluri construită în timpul primei treceri.

Rezultatul final al majorității asamblatorilor este un val de instrucțiuni binare relocalizabile. Codul binar este relocalizabil când adresele operanzilor sunt relaționale cu locația unde este liber să încarce acest cod oricând dorește. Luați de exemplu următorul cod MARIE din Tabela 4.5

Îcarcă x

Adaugă y

Însumează z

Oprire

x, DEC 35

y, DEC – 23

z, HEX 0000

Rezultatul codului asamblat ar putea arăta similar cu acesta:

1+004

3+005

2+006

7000

0023

FFE9

0000

Semnul “+” din exemplul nostru nu trebuie luat literal. El semnalează încărcatul programului ca 004 în prima instrucțiune, este legată de adresa de start a programului. Luați în considerare ce se întâmplă dacă încărcătorul se întâmplă să pună programul în memorie la adresa 250h. Imaginea din memorie ar apărea așa cum e arătată în tabelul 8.1.

Tabelul 8.1.: Memoria dacă programul este încărcat începând de la adresa 250h

Dacă încărcatul se întâmplă să creadă că memoria la adresa 400h era un loc mai bun pentru program, imaginea memoriei ar arăta ca în tabelul 8.2.

Tabelul 8.2. Memoria dacă programul este încărcat începând de la 400h

În contrast cu codul relocalizabil, codul absolut este cod binar executabil care trebuie întotdeauna să fie localizat într-o anumită locație în memorie. Codul nerelocalizabil este folsit pentru scopuri specifice pe anumite sisteme de calculatoare. De obicei, aceste aplicații implică un control explicit al dispozitivelor atașate sau manipularea softului de sistem, în care anumite rutine soft pot fi întotdeauna găsite în locații clar definite.

Desigur, instrucțiunile binare ale mașinii nu pot fi furnizate cu semnele “+” pentru a distinge între codurile relocalizabile și nerelocalizabile. Maniera specifică în care este făcută distincția depinde de designul sistemelor de operare care va rula codul. Unul din cele mai simple moduri de a distinge între cele două este să folosească diferite tipuri de fișiere (extensii) pentru acest scop. Sistemul de operare MS – DOS folsește o extensie.COM (un fișier de comandă) pentru codul nerelocalizbil și o extensie .EXE (un fișier Executabil) pentru codul relocalizabil. Fișierele EXE pot încărca oriunde și chiar de nu e nevoie să ocupe spațiu de memorie contingentă. Fișierele COM întotdeauna încarcă la adresa 100h. codul relocalizabil poate fi de asemenea deosebit de codul nerelocalizabil prin pregătirea codului binar executabil cu prefix sau infomație preambul care informează încărcătorul despre opțiunile sale în timp ce citește fișierul programului de pe disc. Când codul relocalizabil este încărcat în memorie, regiștrii speciali oferă adresa de bază pentru program. Toate adresele din program sunt atunci considerate a fi offset – uri de la adresa de bază stocată în registru. În tabeleul 8.1, unde ni s-a arătat plasarea codului la adresa 0250h un sistem real ar stoca simplu 0250 în registrul de adrese de bază din program și folosește programul fără modificare, ca în baza din program și folosește programul fără modificare ca în tabelul 8.3 unde adresa fiecărui operand devine o adresă efectivă după ce a fost mărită de 0250 stocări în registrul de adrese de bază.

Tabelul 8.3: Memoria dacă programul e încărcat la adresa 250h folosind registrul de adrese de bază.

Iniferent dacă avem cod relocalizabil sau nerelocalizabil instrucțiunile unui program și datele trebuie să fie legate de actuala adresă fizică. Legarea instrucțiunilor și datlor de adrese de memorie se poate întâmpla la timpul de alcătuire, timpul de încărcare sau timpul de execuție. Codul absolut este un exemplu de legare la timp de alcătuire, unde referințele la instrucțiuni și date sunt legate de adresele fizice atunci când programul este compilat. Legarea la timpul de alcătuire lucrează doar dacă locația de încărcare a memoriei pentru imaginea unui proces este cunoscută în avans. Totuși sub legarea la timpul de alcătuire dacă locația de început a imaginii procesului se schimbă, codul trebuie să fie realcătuit. Dacă locația memoriei de încărcare pentru imaginea unui proces nu este cunoscută la timpul de alcătuire codul relocalizabil este generat, care poate fi legat fie la timpul de încărcare fie la timpul de rulare.

Legarea la timpul de încărcare adaugă adresa de start a imaginii procesului la fiecare referință pe când modulul binar este încărcat în memorie. Totuși imaginea procesului nu poate fi uitată în timpul execuțiri pentru că adresa de start pentru proces trebuie să rămână aceeași.

Legarea la timpul de rulare (sau lagarea la timpul de execuție) amână legarea până procesul rulează. Aceasta permite imaginea procesului să fie mutată de la o locație de memorie la alta, pe când execută. Legarea la timpul de execuție cere suport hard special pentru harta adresei sau translatarea dintr-o adresă de proces logic la o adresă fizică. Un registru special de bază stochează adresa de pornire a programului. Această adresă este adăugată fiecărei referințe generate de CPU. Dacă imaginea procesului este mutată registrul de bază este separatat pentru a reflecta noua adresă de pornire a procesului. Este necesar hard de memorie virtuală adițional pentru a realiza rapid această tranzacție.

8.4.2. Editorul de linkuri

La majoritatea sistemelor rezultatul compilatorului de program trebuie să treacă printr-un editor de linkuri (sau linker) înainte să poată fi executat pe sistemul țintă. Legarea (linkingul) este procesul de potrivire a simbolurilor exoterne ale unui program de toate simbolurile exportate din alte fișiere producând un singur fișier binar, fără simboluri externe nerezolvate.

Principala treabă a unui editor de linkuri așa cum arată fig. 8.6 este să combine fișierele programelor asociate într-un modul încărcabil unificat (exemplul din fig. folosește extensii de fișiere caracteristice unui mediu DOS /WINDOWS). Fișierele binare constituente pot fi în întregime scrise de utilizator sau pot fi combinate cu rutine standard de sistem, depinzând de nevolie aplicației. Mai mult, începutul linkerului binar poate fi produs de orice compilator. Printre alte lucruri, aceasta permite variatelor secțiuni ale unui program să fie scrise în limbi diferite deci parte a unui program poate fi scris în C++, pentru ușurința codării iar altă parte ar putea fi scrisă în limbaj de asamblare pentru a mări viteza execuției într-o anumită secțiune înceată a codului.

Fig. 8.6: Legarea și încăscarea modulelor binare

Deoarece cu cu asamblatorii majoritatea editorilor de linkuri cer două treceri pentru a produce un modul de încărcare complet cuprinzând două treceri pentru a produce un modul de încărcare complet cuprinzând toate modulele de input în timpul primei sale treceri, linkerul produce un tabel global de simboluri externe conținând numele fiecărui modul extern și adresele lor relative de start, cu referire la începutul modelului total legat. În timpul celei de-a doua treceri, toate referințele între modulele (separate anterior și externe) sunt înlocuite cu înlocuiri pentru acele module din tabelul de simboluri. În timpul celei de-a doua treceri a linkerului, codul dependent de platformă poate de asemenea să fie adăugat la modulul combinat, producând un fișier de program binar încărcabil și unificat.

8.4.3. Biblioteci de linkuri dinamice (DLL)

Unele sisteme de operare, notabile Microsoft Windows, nu cer editaarea de linkuri a tuturor procedurilor folosite de un program înainte de creerea unui modul executabil. Cu sintaxta corespunzătoare în programul sursă, anumite module externe pot fi legate la timpul de rulare. Aceste module externesunt numite biblioteci de linkuri dinamice (DLL – uri), pentru că legarea este făcută doar când programul sau modulul este invocat mai întâi. Procesul de legare dinamică este arătat schematic în fig. 8.7. Pe măsură ce fiecare procedură este încărcată, adresa sa este plasată într-un tabel de referințe – încrucișate în interiorul modulului principalului program .

Fig. 8.7: Legarea dinamică cu hotărârea adresei timpului de încărcare.

Această abordare are multe avantaje. Mai întâi, dacă un modu extern este folosit repetat de câteva programe, legarea statică ar cere ca fiecare din aceste programe să includă o copie a codului binar al nucleelor. În mod clar, este o pierdere de spațiu de disc să ai multiple copii ale aceluiași cod, deci economisim spații legând la codul de rulare. Al doilea avantaj al legării dinamice este că dacă codul într-unul din modulele externe se schimbă, atunci fiecare modul care a fost legat cu el nu are nevoie să fie relegat pentru a păstra integritatea programului. Mai mult, pastrând urma a ce module angajează anumite module externe, poate fi dificil – poate imposibil – pentru sisteme mari. În al treilea rând legarea dinamică oferă mijloacele prin care trei grupuri pot crea biblioteci comune, prezența cărora poate fi presupusă de oricine care scrie programe pentru un anumit sistem cu alte cuvinte, dacă scrii un program pentru o anume marcă de sisteme de operare, poți lua ca sigur faptul că anumite biblioteci specifice vor fi disponibile pe fiecare computer care rulează acel sistem de operare. Nu ai nevoie să porți grija numărului de versiune a sistemului de operare sau a nivelului pachetului, sau altceva care este înclinat la schimbări frecvente. Atât timp cât biblioteca nu e niciodată șterarsă, poate fi folosită pentru legarea dinamică.

Legarea dinamică poate avea loc fie când un program este încărcat, fie când o procedură nelegată este mai întâi chemată de un program în timp ce rulează. Legătura dinamică la timpul de încărcare cauzează întârzieri în pornirea programului. În loc de a citi simplu codul binar al sistemului de pe disc și să-l ruleze, sistemul de operare nu numai că încarcă pricipalul program ci încarcă și binarele pentru toate modulele pe care le folosește programul. Încărcătorul oferă adresa de încărcare a fiecărui modul principalului program anterior executării primei afirmații a programului. Decalajul dintre momentul în care utilizatorul invocă programul și până începe executarea sa propriu-zisă, poate fi inacceptabil pentru unele aplicații. Pe de altă parte, legarea la timpul de rulare nu atrage penalizările de porinire ale legărilor la timpul de încărcare, pentru că un modul este legat doar dacă se cere. Aceasta salvează o cantitate considerabilă de muncă când relativ puține dintre modulele unui program sunt invocate. Totuși, unii utilizatori obiectează la timpurile de răspuns percepute haotic când un program care rulează se oprește să încarce rutinele bibliotecii.

O problemă mai puțin evidentă este aceea că scrierea modulului de către programator nu are un control direct asupra conținuturilor rutinei bibliotecii linkului dinamic. Totuși dacă autorii codului bibliotecii link decid să-i schimbe funcționalitatea, ei pot face asta fără știrea sau consimțământul oamenilor care folosesc biblioteca. În plus așa după cum oricine care a scris programe comerciale poate spune, cele mai mici schimbări în rutinele acestor boblioteci poate cauza efecte de real în interiorul întregului sistem. Aceste efecte pot fi dezbinante și foarte greu să dai de urma lor.

Din fericire asemenea surprize sunt rare, deci legarea dinamică continuă să fie o abordare favorită pentru distribuția codului binar comercial peste întregile clase ale sistemelor de operare.

8.4.4. Compilatorii.

Programarea limbajului de asamblare poate face multe lucruri pe care limbajele de nivel înalt nu le pot face. Mai întâi, limbajul de asamblare dă programatorului acces direct la arhitectura mașinii de dedesupt. Programele folosite să controleze și/sau să comunice cu dispozitivele periferice sunt scrise tipic în ansamblu datorită intrucțiunilor speciale disponibile în asamblare care nu sunt disponibile de obicei în limbajele de nivel mai înalt.

Un programator nu trebuie să se bazeze pe serviciile sistemelor de operare pentru a controla un port de comunicații. De exemplu: Folosind limbajul de asamblare poți face ca mașina să facă totul, chiar acele lucruri pentru care serviciile sistemelor de operare nu sunt oferite. În particular, programatorii folosesc adesea limbajul de asamblare pentru a obține avantaje din hardurile specializate deoarece compilatorii pentru limbajele de nivel mai înalt nu sunt concepute pentru a utiliza dispozitivele necomune sau nefolosite comun. De asemenea codul de asamblare bine scris stălucește cu rapiditate. Fiecare instrucțiune primitivă poate fi îmbunătățită astfel încât să producă cea mai eficientă acțiune asupra sistemului.

Aceste avantaje touși nu sunt motive suficiente pentru a folosi limbajul de asamblare pentru dezvoltarea aplicației generale. Faptul ramâne că programarea în limbaj de asamblare este dificilă și predispusă la erori. Este chiar mai dificil să menții decât să scrii în special dacă programatorul mentenanței nu este autorul original al sistemului. Mai important, limbajele de asamblare nu sunt portabile pe diferite arhitecturi de mașini. Pentru aceste motive, majoritatea softului de sistem de scpo general conține foarte puține instrucțiuni de asamblare sau chiar deloc. Codul de asablare este folosit doar când este absolut necesar să faci asta.

Asăzi, virutal toate sistemele și programele de aplicare folosesc limbajele de nivel mei mare aproape în exclusivitate. Desigur “nivel mai mare” este un termen relativ, obiect al neînțelegerilor. Cineva acceptă că taxonomia pentru limbajele de programare începe cu chemarea codului binar mașină, limbajul calculatoarelor de primă generație. (1 GL).

Programatorii acestui 1 GL au introdus mai întâi program de instrucțiuni direct în mașină folosind mecanisme cu pârghii cotite pe consola sistemului. Utilizatorii mai “privilegiați” au perforat instrucțiuni binare pe hârtie sau carduri. Productivitatea programării a crescut când primii asamblatori s-au scris în prima parte a anilor 1950. aceste limbaje a doua generație (2 GL) au eliminat erorile introduse când instrucțiunile au fost traduse în con mașină de mână. Al doilea salt al productivității s-a produs cu introducerea limbajelor simbolic compilate sau limbajele de “a treia generație” (3 GL). În ultima parte a anilor 1950 FORTRAN (formulă de translație) a fost primu dintre aceștia, dat de către JOHN BACKUS și echipa sa de la IBM în 1957. în anii de după o veritabilă supă alfabetică de 3 GL – uri a turnat asupra comunității programatorilor. Numele lor sunt uneori acronime, cum ar fi: COBOL, SNOBOL și COOL. Uneori sunt numite după oameni ca PASCAL și ADA. Nu rar, 3 GL – urile sunt numite cum au chef programatorii să le numească așa ca în cazurile C, C++, și Java.

Fiecare generație de limbaje de programare se apropie mai mult de modul în care se gândesc oamenii la probleme și mai puțin de cum le rezolvă mașinile. Unele limbaje de a patra și a cincea generație sunt atât de ușor de folosit încât sarcinile de programare care anterior cereau un programator pregătit profesional, pot ușor fi făcute de utilizator ideea cheie fiind că utilizatorul pur și simplu spune computerului ce să facă nu cum să facă. Compilatorul își dă seama de restul. În a fec lucrurile mai simple pentru utilzator aceste limbaje de ultimă generație plasează sarcini substanțiale asupra sistemelor computerului. În cele din urmă toate instrucțiunile trebuie împinse în jos prin ierarhia limbajului, pentru că hardul digital care de fapt face munca poate executa doar instrucțiuni binare.

În capitolul 4 am arătat că există o corespondență unu la unu între afirmațiile limbajului de asamblare pe care-l rulează de fapt mașina. În limbajele compilate aceasta este o reacție unu la mulți. De exemplu, permițând definițiile stocate variabil afirmația în limbaj de nivel înalt x = 3*1 s-ar putea să ceară cel puțin 12 afirmații de program în limbajul de programare MARIE. Raportul dintre instrucțiunile codului sursă și instrucțiunile mașinii binare devine mai mic către sofisticarea limbajului sursă. Cu cât e mai înalt limbajul cu atât mai multe intrucțiuni da mașină genereză tipic fiecare linie din program. Această relație este arătată în ierarhia limbajelor de programare în fig. 8.8

Fig. 8.8: O ierarhie a limbajelor de programare

Știința scrierii compilatoarelor a continuat să se îmbunătățească de când primii compilatori s-au scris, în ultima parte a anilor 1950. Prin realizările sale în construcția compilatoarilor, știința ingineriei de soft și-a dovedit abilitatea de a converti probleme aparent dificile în sarcini de programare de rutină. Dificultatea problemei stă în realizarea unui pod în diferența semntică între afirmații care au sens pentru oameni și afirmații care au sens pentru mașini.

Majoritatea compilatorilor efectuează această transformare folosind un proces în 6 faze, arătat în fig. 8.9. Primul pas în compilarea codului, numit analiză lexicală, țintește să atragă primitive de limbaj, sau simboluri dintr-un șuvoi de cod sursă textual. Aceste simboluri constau în cuvinte rezervate, particulare pentru un limbaj (exp. If, else – dacă, atunci), operatori matematici și Booleeni și variabilele definite de programator. În timp ce analizatorul lexical creează șuvoiul de simboluri, el construiește și structura pentru un tabel de simboluri. În acest punct, tabela de simboluri conține cel mai probabil simboluri definite de utilizator (variabile și nume de proceduri), împreună cu adnotări, cu locația lor și tipul de date. Erorile lexicale apar când caracterele sau construcțiile străine limbii sunt descoperite în codul sursă. Variabilele definite de programator 1 Days Pay (plată de o zi), de exemplu ar produce o eroare lexicală în majoritatea limbajelor pentru că numele variabilelor tipic nu pot începe cu o cifră. Dacă nu se găsesc erori, compilatorul trece la analiza sintaxei șufoiului de simboluri.

Fig. 8.9: Cele 6 faze ale compilării programului.

Analiza sintaxei, sau analiza sintactică, a șuvoiului de simboluri implică crearea unei structuri de date numită arbore de analiză sau arbore de sintaxă.

Transformarea unui arbore de analiză de obicei dă expresia analizată. Să considerăm, de exemplu, următoarea afirmație de program: luna Principală = plata – (balanța neplătită .rata de interes).

Un arbore de sintaxă de sinteză pentru această afirmație este arătat în fig. 8.10.

Fig. 8.10 Un arbore de sintaxă

Analizatorul verifică tabelul de simboluri pentru prezența variabilelor definite de programator, care există în arbore.

Dacă analizatorul întâlnește o variabilă pentru care nu există o descriere în tabelul de simboluri, el dă un mesaj de eroare. De asemenea analizatorul detectează construcțiile ilegale cum ar fi: A = B+C = D. Ceea ce nu face analizatorul este că nu verifică dacă operatorii = sau + sunt valizi pentru variabilele A,B,C,D. Analizatorul semantic face asta în următoarea fază. El folosește arborele de analiză ca input și îl verifică pentru tipurile de date corespunzătoare folosind informația din tabelul de simboluri. Analizatorul semantic, face de asemenea, promoții de tipuri de date corespunzătoare, cum ar fi schimbarea unui întreg într.o valoare cu punct de plutire sau variabilă, dacă asemenea promoții sunt suportate de regulile limbajului.

După ce compilerul a completat funcțiile sale de analiză, începe faza sa de sinteză din faza analizei semantice. Primul pas în sinteza codului este să creeze un cod de pseudoasamblare din arborele de sintaxă. La acest cod se face adesea referire ca la codul de trei adrese, pentru că suportă afirmații cum ar fi: A = B+C, pe care majoritatea limbajelor de asamblare nu le suportă. Acest cod intermediar permite compilatorilor să fie portabili pentru multe tipuri de calculatoare.

Odată ce sunt făcute simbolizarea,construirea arborelui și analizele semantice, devine o sarcină relativ ușoară să scrii un translator de cod de 3 adrese care produce output pentru un număr sau diferite seturi de instrucțiuni. Majoritatea ISA ale sistemelor folosesc codul de 2 adrese, deci diferențele modului de adresare trebuie să fie rezolvate în timpul procesului de traducere (Amintiți-vă că setul de instrucțiuni MARIE este o arhitectură cu o adresă). Faza finală a compilatorului face totuși adesea mai mult decât doar să traducă codul intermediar în instrucțiuni de asamblare. Compilatorii buni fac unele încercări la optimizarea codului, care pot lua în considerare diferite organizări de memorie și regiștri precum și faptul că oferă cele mai puternice instrucțiuni de care e nevoie pentru a îndeplini sarcina. Optimizarea codului implică și îndepărtarea variabilelor temporare nenecesare, transformând expresiile repetate în expresii singure, și marcarea codului mort (care nu mai poate fi atins).

După ce toate instrucțiunile au fost generate și optimizarile au fost făcute acolo unde era posibil, compilatorul creează cod de obiect binar, potrivit pentru legarea și execuția pe sistemul țintă.

8.4.5. Translatorii (interpreții)

Ca și limbajele compilate, limbajele interpretate au de asemenea o relație unul – la – mai mulți între afirmațiile codului sursă și instrucțiunile executabile ale mașinii. Totuși, spre deosebire de compilatori, care citesc întregul fișier al codului sursă înainte de producerea unui șuvoi binar, interpreții o singură afirmație sursă într-un moment.

Cu atât de multă muncă făcută, interpreții sunt mult mai înceți decât compilatorii. Cel puțin 5 din cei 6 pași ceruți de compilatori, de asemenea trebuie să fie realizați în interpreți, iar acești pași sunt realizați în “timp real”. Această abordare nu permite nici o oportunitate pentru optimizarea codului. Mai mult, detectarea eroerilor în interpreți este de obicei limitată la sintaxa limbajului verificarea tipului de variabile. De exemplu, foarte puțini interpreți detectează posibile operații aritmetice ilegale înainte ca ele să se întâmple sau avertizează programatorul înainte de depășirea legăturilor unui dispozitiv.

Unii interpreți de început, notebil unii interpreți BASIC, ofereau verificarea sintaxei în interiorul editorilor concepuți la comandă. De exemplu dacă un utilizatoș scria „este” în loc de „else” editorul afișa imediat o remarcă referitor la acest lucru. Alți interpreți permit folosirea editorilor de text cu scop general, întârziind verificarea sintaxei până la timpul de execuție. Ultima abordare este în particular riscantă când este folosită pentru programele cu aplicații critice de afaceri. Dacă programul aplicației se întâmplă să execute o ramură de cod care nu a fost verificată pentru sintaxa corespunzătoare, programul clachează lasând utilizatorul să se uite la o afișare care arată ciudat a sistemului, pe când fișierele sal probabil au updatat-o doar parțial. În ciuda vitezei de execuție greoaie și a verificării întârziate a erorilor, există motive bune pentru a folosi un limbaj interpretat. Printre motive este și acela că limbajele interpretate permit debuggingul nivelului sursă facându-le ideale pentru începerea programatorilor și închierea utilizatorilor. De aceea, în 1964, 2 profesori la Dartmouth, John G. Kemeny și Thomas E. Kurtz au inventat BASIC, Codul de Instrucțiuni Simbolice pentru Toate Scopurile pentru Începători. În acel timp primele experiențe de programare ale studenților implicau perforarea instrucțiunilor FORTRAN pe carduri cu 80 de coloane. Cardurile erau apoi rulate printr-un compilator mainframe, care avea adesea un timp de răspuns măsurat în ore. Uneori treceau zile înainte ca o compilație curată și o execuție să poată fi realizate. În depărtarea sa dramatică de la afirmațiile de compilare în mod de grup, BASIC – ul a permis studenților să tipărească afirmațiile programului în timpul unei sesiuni interactive la terminare. Interpretul BASIC care rula continuu pe mainframe (structura principală) dădea studenților feedback imediat. Ei puteau corecta repede erorile de sintaxă și logică, creând astfel o experiență de învățare pozitivă și efectivă.

Pentru aceste motive, BASIC de ales pentru primele sisteme de PC – uri. Mulți cumpărători de la început nu erau programatori experimentați, deci aveau nevoie de un limbaj care să facă ușor de învățat programarea de către ei. BASIC era ideal în acest scop. Mai mult, pe un sistem personal, pentru un singur utilizator, la foarte puțini oameni le păsa că BASIC era mult mai încet decât un limbaj compilat.

8.5. Java – Totul deasupra

În prima parte a anilor 1990 Dr. James Gosling și echipa sa de la Sun Microsystem au început să creeze un limbaj de programare care ar rula pe orice platformă de calcul. Trebuiau să creeze un limbaj de calculator „scrie o dată, rulează oriunde”. În 1995, Sun a lansat prima versiune a limbajului de programare Java. Datoritaă particularității și specificațiilor deschise, Java a devenit enorm de popular. Codul Java este rulabil virtual pe toate platformele de computer, de la cele mai mici dispozitive portabile până la cele mai mari structuri. Java este un limbaj platformă – încrucișată care era desfășurabil la începutul comerțului bazat pe Internet pe scară largă, modelul perfect de calcul cu platformă – încrucișată. Deși Java și câteva din caracteristicile sale au fost pe scurt introduse în cap. 5, intrăm acum în mai multe detalii.

Dacă ați studiat vreodată limbajul de programare Java, știți că outputul din compilatorul Java este un fișier de clasă binară. Acest fișier de clasă este executabil de o Mașină Virtuală Java (JVM) care se aseamană cu o mașină reală din multe puncte de vedere. Are zone de memorie privată adresabile doar de către procesele care rulează în interesul mașinii. Are de asemenea propria sa arhitectură cu set de instrucțiuni bona fide (de bună credință). Acest ISA menține mașina simplă și portabilă practic pentru orice platformă de calcul. Desigur, o Mașină Viruala Java nu este o mașină reală. Este un strat de soft care se află între sistemele de operare și programe de aplicație: un fișier de clasă binară. Fișierele de clasă includ variabilele precum și metodele (procedurile) de manipulare a acelor variabile.

Figura 8.11 ilustrează cum JAVA este o mașină de calcul în miniatură cu zonă proprie de memorie și metodă. Observați că încărcarea memoriei, codul metodei, și zonele de „interfață a metodei native” sunt împărțite printre toate procesele care rulează în interiorul mașinii.

Fig. 8.11: Mașina Virtuală Java

Încărcătura memoriei este principalul spațiu de memorie care este alocat și dealocat pe când structurile de date sunt create și distruse prin execuție. Dealocarea Java a memoriei încărcate este numită “colecție de gunoi”, pe care JVM (în locul sitemelor de operare) o face automat. Zona de metodă nativă Java furnizează spațiul de lucru pentru obiectele binare externe Java, cum ar fi modulele compilate C++ sau modulele limbajului de asamblare. Zona de metodă JVM conține codul binar cerut pentru a rula fiecare fir de aplicație din JAVA. Aici rezidă structurile de bază variabile și afirmațiile de program cerute de clasă. Afirmațiile de program executabile Java sunt stocate într-un cod intermediar numit bytecode, de asemenea introdus în capitolul 5.

Bytecodul metodei Java este executat în interiorul diferitelor procese de fir. Câteva procese de fir sunt pornite automat de JVM, firul programului principal fiind unul dintre ele. Doar o mașină metodă poate fi activă la un moment dat în fiecare fir, iar programele pot genera fire adiționale pentru a oferi unirea. Când un fie evocă o metodă, el creează o structură de memorie pentru metodă. O parte din această structură de memorie este folosită pentru variabilele locale ale metodei și e altă parte pentru teancul său privat. După ce firul a definit teancul de metode, el arată paramatrii metodelor și jetonul de program primei afirmații executabile a metodei.

Fiecare clasă Java conține un tip de tabel de simboluri numit bazin constant care este un dispozitiv ce conține informația despre tipul de date a fiecăreia dintre variabilele unei clase și valoarea inițială a variabilei, precum și marcajele de acces pentru variabile (de exempu dacă este publică sau privată pentru clasă). Bazinul constant conține și câteva structuri, altele decât acelea definite de către programator. De aceea Sun Microsystems numește intrările în bazinul constant (elementele de ordine), atribute. Printre atributele fiecărei clase Java, se gasește păstrarea itemurilor ca numele fișierului sursă Java, parte din ierarhia moștenirii sale și indicatorii către alte structuri de date interne Java.

Pentru a ilustra cum execută JVM bytecodul metodei, să considerăm programul Java arătat în fig. 8.12

clasă publică Simplă {

principalul vid static public (String[] args){

int i = 0;

dublu j = 0

în timp ce (i<10){

i = i+1

j = j+1.0;

}// în timp ce

}// principal ()

}// Simplu ()

Fig. 8.12: Un program Java Simplu

Java cere codul sursă pentru această clasă să fie stocat într-un fișier text numit Simplu.Java. Compilatorul Java citește Simplu.Java și face toate lucrurile pe care le fac alți alți compilatori. Outputul său este un șuvoi binar de bytecode numit Simplu.clasă. Fișierul Simplu.clasă poate fi rulat de orice JVM de versiune egală sau mai nouă decât de acela al compilatorului care a creat clasa. Acești pași sunt arătați în fig. 8.13

Fig. 8.13 Compilația și execuția de clasă Java

La timpul de execuție, o mașină virtuală Java trebuie să ruleze pe sistemul gazdă. Când Java încarcă un fișier clasă, primul lucru pecare-l face e să verifice integritatea bztecodului prin verificarea formatului de fișier clasă, verificarea formatului instrucțiunilor bytecodului și asigurându-se că nu se fac referințe ilegale.

După ce verificarea sa preliminară este terminată cu succes, încărcătorul realizează un număr de verificări ale timpului de rulare, în timp ce plasează bytecodul în memorie.

După ce s-au realizat toți pașii de verificare, încărcătorul cere interpretul bytecodului. Acest interpret are 6 faze în care va:

Realiza o editare de link a instrucțiunilor bytecodului cerând și sistemele binare, dacă nu sunt deja încărcate.

Creea și analiza structura stocului principal și variabilele locale

Creea și porni firul/firele de execuție;

În timp ce se execută firele, se manageriază stocarea încărcăturii prin dealocarea acumulării nefolosite;

Pe măsură ce fiecare fir moare, dealocă resursele sale;

După terminarea programului va omorî orice fir rămas și va termina JVM.

Fig. 8.14 arată imaginea hexadecimală a bytecodului pentru Simple.class. Adresa fiecărui byte poate fi găsită adăugând valoare în prima coloană (colorată) offsetului din primul rând (colorat). Pentru convenție am tradus bytecodul în caractere unde valoarea binară are o valoare semnificativă 7- bit ASCII. Poți vedea numele fișierului sursă, Simplu.java, începând cu adresa 06Dh. Numele clasei începe la 080h. Cititorii familiari cu Java sunt conștienți că Simplu.clasă este cunoscută și ca această clasă, iar superclasa sa este .java.lang.Object, numele căreia începe la adresa 089h.

Fig. 8.14. Imagine binară a simple.class

Notați că fișierul nostru clasă începe cu nr. hex CAFEBABE. Este nr. magic care indică începutul unui fișier clasă (și da, este politic incorect). O secvență de 8 – biți care indică versiunea limbajului fișierului clasei urmează după nr. magic. Dacă acest nr. secvență e mai mare decât versiunea pe care JVM interpret o poate suporta, verificatorul încheie JVM.

Bytecodul executabil începe la adresa 0E6h. Cifrele hex, 16, la adresa 0E5h anunță interpretul că bytecodul metodei executabile e lung de 22 biți. Ca și în limbajele de asamblare, fiecare bytecod executabil are un mnemonic corespunzător. Java definește curent 204 intsrucțiuni bytecode diferite. Totuși, e nevoie doar de 1 byte pentru întregul lanț de opcoduri. Aceste mici opcoduri ajută la păstrarea claselor mici, făcându-le rapide la încărcat și ușor de convertit în instrucțiuni binare pe sistemul gazdă.

Pentru că anumite constante mici sunt folosite atât de frecvent în programele de computer, bytecodurile au fost definite în special pentru a furniza aceste constante acolo unde e nevoie. De exemplu, iconst_5 mnemonică împinge numărul 5 în teanc. Pentru ca să împingă constantele mai mari în teanc, se cer 2 bytecoduri, primul pentru operație, al doilea pentru operator. După cum am menționat deasupra, variabilele locale pentru fiecare clasă sunt păstrate într-o ordine.

Caracteristic, primele câteva elemente ale acestei ordini sunt în majoritate active, deci există bytecoduri particulare pentru adresarea acestor elemente de ordine locală inițială. Accesul în alte poziții din ordine cere o instrucțiune de 2 biți: una pentru opcode și a doua pentru offsetul elementului de ordine.

Acestea fiind spuse, să privim la bytecodul pentru principala ( ) metodă Simple.class. Am extras bytecodurile din Fig. 8.14 și l-am listat în fig. 8.15 împreună cu mnemonicii și comentariile. Coloana rămasă dă adresa relativă a fiecărei instrucțiuni. Jetonul programului fir – specific folosește această adresă relativă pentru a controla curgerea programului. Trasăm acum execuția acestui bytecode, astfel încât să puteți vedea cum funcționează.

Fig. 8.15: Bytecodul adnotat pentru Simple.class

Când interpretul începe rularea acestui cod, PC – ul este inițial setat la 0, deci este executată instrucțiunea iconst_0. Aceasta este execuția afirmației int i =0; din a III – a linie a codului sursă Simple.java. PC – ul este incrementat de unu și după aceea execută fiecare instrucțiune inițializată, până întâlnește afirmația gata la instrucțiunea 4. Această instrucțiune adaugă un 11 decimal la jetonul programului, deci valoarea sa devine 0Fh, care arată la instrucțiunea load_1 (încarcă 1)

În acest punct, JVM a alocat valorile inițiale la i și j și trece acum să verifice condiția inițială a inelului pentru a vedea dacă corpul inelului ar trebui executat. Pentru a face aceasta, ea plasează valoarea lui i (din ordinea variabilelor locale) pe teanc, și apoi înaintează valoarea comparației 0Ah. Notați că acest lucru este puțin din optimizarea codului care a fost făcută pentru noi de compilator. Prin absență, Java stochează valorile numerelor în 32 biți, ocupând astfel 4 biți. Totuși, compilatorul este destul de inteligent să vadă că constanta decimală 10 e destul de mică pentru a stoca într-un bit, deci el a scris codul pentru a înainta un singur bit, nu 4 biți pe teanc.

Instrucțiunea operației de comparare, if – icmplt, trece la i și 0Ah și compară valorile lor (it de la sfârșitul mnemonicului înseamnă că ea caută mai puțin decât condiția). Dacă i e mai puțin decât 10, 0Bh este scăzut din PC, dând 7, care este adresa de start pentru corpul inelului. Când instrucțiunile din interiorul corpului nivelului s-au încheiat, execuția cade la procesul condițional la adresa 0Fh. Odată ce această condiție devine falsă, interpretul reîntoarce controlul la sistemele de operare, după ce face curățenie.

Programatorii Java, care s-au întrebat cum știe interpretul care linie de sursă a cauzat o cădere de program, vor găsi răspunsul începând de la adresa 108h în imaginea fișierului clasei binare în Fig. 8.14. Acolo este începutul tabelului numărului de linii care asociază valoarea jetonului programului cu o anumită linie în programul sursă. Cei doi biți începând la adresa 106h spun JVM că există 6 intrări în tabelul numărului de linii care urmează. Completând câteva detalii, putem construi legătura încrucișată în fig. 8.16

Fig. 8.16: Un jeton de program la legătrua linie-încrucișată a sursei pt. Simple.class

Observați că dacă programul se oprește când PC = 9, de exp, linia greșită a programului sursei ar fi linia 6. Interpretarea bytecodului generat pentru linia de cod nr. 7 a sursei începe când PC e mai mare sau egal cu 0Bh, dar nu mai mic decât 0Fh.

Pentru că JVM face atât de mult încât încarcă și execută bytecodul său, nu se poate potrivi cu performanța unui limbaj compilat. Acest lucru e adevărat chiar și când se folosește un soft de mărime a vitezei ca, compilerul Java’s Just in Time (JIT). Afacerea totuși, este că fișierele clasă pot fi crate și stocate pe o platformă și executate pe o platformă complet diferită. De exemplu, putem scrie și compila un program Java pe un server Alpha RISC și el va rula la fel de bine ca pe clienții de clasă CISC – Pentium care descarcă bytecodul fișierului clasă. Această paradigmă „scris o dată, rulează-oriunde” este de un beneficiu enorm pentru anteprizele cu sisteme disparate și separate geografic.

„Applet – ii” Java (bytecoduri care rulează în browsere) sunt esențiali pentru tranzacțiile bazate pe web și comerț electronic. În cele din urmă, tot ceea e cerut de utilizator e să fie soft pentru browser care să ruleze (rezonabil). Datorită portabilității sale și a reltivei ușurințe de folosire, limbajul Java și mediul mașinii sale virtuale sunt platforme middleware ideale.

8.6 Softul Bazelor de date

De departe, cele mai prețioase bunuri ale unei antreprize nu sunt birourile sau fabricile sale, ci datele. Indiferent de natura antreprizei – o afacere privată, o instituție educațională, sau o agenție guvernamentală – înregistrarea definitivă a istoriei sale și starea curentă sunt imprimate asupra datelor sale. Dacă datele sunt inconsecvente față de starea antreprizei sau dacă datele sunt inconsecvente față de ele însele, utilitatea sa este îndoielnică și cu siguranță se ridică probleme.

Orice sistem de computer care suportă o antrepriză este o platformă pentru programele de aplicații interrelaționale. Aceste programe realizează updatări ale datelor în concordanță cu schimbările stării antreprizei. Grupurile de programe interrelaționale sunt numite adesea sisteme de aplicație pentru că ele lucrează împreună ca un întreg integrat. Puține piese de sine stătătoare sunt foarte folositoare. Componentele sistemelor de aplicație împart același set de date și tipic, dar nu necesar, împart același mediu de calcul. Astăzi, sistemele de aplicații folosesc multe platforme: microcomputere desktop, servere de fișiere și structuri principale. Cu intrarea în vogă a calculelor cooperative bazate pe web, uneori nici măcar nu știm sau nu ne pasă unde rulează aplicația. Deși fiecare platformă aduce beneficiile sale unice și provocările la știința managementului de date, conceptele fundamentale ale softului managementului bazelor de date au răspuns neschimbate timp de mai mult de 3 decade.

Primele sisteme de aplicații înregistrau datele prin folosirea benzii magnetice sau cardurilor perforate. Prin natura lor secvențială, update – urile benzilor și cardurilor perforate trebuiau să fie rulate ca grup, în mod de procesare a grupurilor, pentru eficiență. Pentru că fiecare element de date pe disc magnetic poate fi accesat direct, procesarea de grup a update – urilor împotriva fișierelor flat (plate) nu a mai fost forțată de arhitectura sistemelor. Totuși, vechile obiceiuri sunt greu de înlăturat, iar programele costă pentru a fi rescrise.

Astfel, procesarea fișierelor flat a persistat ani după ce majoritatea cititorilor de carduri au devenit piese de muzeu.

În sistemele de fișiere flat, fiecare program de aplicație este liber să definească orice obiecte de date e nevoie. Din acest motiv, o vedere consistentă a sistemului este dificil de decretat. De exp. să zicem că avem un sistem de primire de primire de conturi, care este un sistem de aplicație care înregistrează cine ne datorează câți bani și de cât timp.

Programul care produce facturi lunare poate posta tranzacții lunare la un câmp cu 6 cifre (sau element da date)numit CUST_OWE. Acum, persoana care face reconcilierile lunare ar putea la fel de bine să muncească acest câmp CUST _ BAL, și se poate aștepta ca el să aibă 5 cifre. E aproape sigur că undeva de-alungul liniei informația va fi pierdută și va domni confuzia. Cândva în timpul lunii, după ce câteva mii de $ nu sunt înregistrați, debugger – ii își vor da seama în cele din urmă că CUST_OWE este același element de date ca și CUST_BAL și că problema a fost cauzată de trunchierea sa supraaglomerarea unui câmp.

Sistemele de management ale bazelor de date (DBMS) au fost create pentru a prveni aceste încurcături. Ele introduc ordinea și consistența asupra sistemelor de aplicații bazate pe fișiere. Cu sistemele de baze de date, programatorii nu mai sunt liberi să descrie și să acceseze un element de date în orice manieră doersc. Există doar una și numai o singură definiție a elementelor de date într-un sistem de management de baze de date. Această definiție este o schemă între vederea programatorului asupra bazelor de date, schema sa logică și concepția sistemului computerului asupra bazelor de date, numită schemă fizică. Sistemele de management ale bazelor de date integrează concepțiile logice și fizice asupra bazelor de date.

Programele de aplicație angajează schema logică prezentată de sistemele de management a bazelor de date în interiorul schemei fizice nule controlul sistemelor de management a bazelor de date si sistemelor de operare.

Figura 8.17 ilustrează această operație.

Fig. 8.17 Relația unui Sistem de Mnagement al bazelor de date cu alte componente ale sistemului.

Elementele datelor individuale definite de o schemă de baze de date sunt organizate în structuri logice numite înregistrări care sunt grupate împreună în fișiere. Fișierele relaționale formează în colectiv baza de date. Arhitecturile bazelor de date sunt atente la nevoile aplicațiilor precum și la performanță când creează scheme fizice și logice. Obiectivul general e să minimizeze redundanța și spațiul irosit în timp ce mențin un nivel dorit de performanță de obicei măsurat în termenii timpului de răspuns al aplicației. Un sistem bancar de exemplu, nu ar plasa numele clientului și adresa pe fiecare înregistrare a cecurilor anulate în baza de date. Această informație ar fi ținută într-un fișier master de conturi care folosește un nr. de cont a și câmpul său cheie. Fiecare cec anulat, apoi, ar trebui să poarte doar nr. de cont împreună cu informația particulară cecului însuși.

Sistemul de management a datelor sunt largi în ceea ce privește modul în care datele sunt organizate fizic. Virtual, fiecare vânzător de baze de date a inventat metode de a manageria și indexa fișierele. Majoritatea sistemelor folosesc o variantă de structură de date arbore B+(vezi apendixul A pentru detalii). Sistemul de management a bazelor de date manageriază topic stocarea discurilor independent de sistemele de operare de dedesupt. Îndepărtând stratul sistemelor de operare din proces, sistemele de baze de date și designul indexului.

În capitolul 7. am studiat organizarea fișierelor de discuri. Am aflat că majoritatea sistemelor de discuri citesc datele pe bucăți de pe disc, cea mai mică unitate adresabilă fiind un sector. Majoritatea sistemelor mari citesc o întreagă pistă o dată. Pentru că o structură index devine foarte adâncă, probabilitatea crește ca noi să avem nevoie de mai mult de o operație de citire pentru a traversa arborele index. Deci, cum organizăm arborele pentru a păstra I/O discului pe cât de nefrecvent putem? E mai bine să creem noduri index interne foarte mari astfel încât să poată trece mai multe înregistrări ale valorilor pe noduri? Asta ar face nr. de noduri pe nivel mai mic și probabil permit ca un întreg nivel de arbore să fie accesat într-o singură operațiune de citire. Sau e mai bine să păstrăm mărimile mici ale nodurilor interne astfel încât să putem citi mai multe straturi ale nodurilor interne într-o singură operațiune de citire?

Răspunsurile la toate aceste întrebări pot fi găsite doar în contextul sistemului particular asupra căruia rulează sistemul de operare. Un răspuns optim poate chiae să depindă de datele înseși. De exemplu decă cheile sunt rare, adică dacă există multe valori ale cheilor posibile care nu sunt folosite, am putea alege doar o anumită schemă de organizare index. Dar cu structurile de index populate dens, am putea alege asta. Indiferent de implementare, scala bazelor de date este o sarcină netrivială care cere o înțelegere a softului managementului bazelor de date, arhitectura de stocare a sistemului și particularitățile populației de date manageriate de sistem.

Fișierele bazelor de date poartă adesea mai mult de un index. De exemplu, dacă ai o bază de date client ar fi o idee bună dacă ai putea localiza înregistrările după nr. de cont al clientului, ca și după nume. Fiecare index, desigur,adaugă cheltuieli, sistemului, atât în termenii de spațiu, (pentru a stoca indexul), cât și de timp (pentru că toți indicii trebuie să fie updatați odată când se adaugă sau se șterg înregistrări.)

Una dintre provocările majore cu care se confruntă designerii de sisteme, este aceea de a fi siguri că există suficienți indici să permită retragerea rapidă a înregistrărilor în majoritatea circumstanțelor, dar nu atât de mulți incât să fie o poartă pentru sistem cu o cantitate excesivă de gospodărie.

Scopul sistemului de management a bazelor de date este de a furniza acces ușor la mari cantitați de date, dar să facă asta în moduri care să asigure integritatea bazelor de date. Asta înseamnă că un sistem al managementului bazelor de date trebuie să permită utilizatorilor să definească și să managerieze regulile, sau constrângerile, plasate pe anumite elemente de date critice. Uneori aceste constrângeri sunt doar simple reguli că “nr clientului nu poate fi nul”. Reguli mai complexe, dictează ce utilizatorii particulari pot vedea ca elemente de date și cum pot fi updatate fișierele cu elemente ale datelor interrelaționale. Definirea și întărirea securității și a constrângerilor integrității datelor sunt critice pentru utilitatea oricărui sistem de baze de date.

Altă componentă de interior a unui sistem de management a bazelor de date este managerul tranzacției sale. Un manager de tranzacție controlează update – urile la obiectele da date într-un asemenea mod încât să se asigure că baza de date este întotdeauna într-o stare consistentă. Formal, un manager al tranzacției controlează schimbările în starea datelor, astfel încât fiecare tranzacție are următoarele proprietăți:

Atomicitate – toate update – urile relaționale au loc în interiorul limitelor tranzacției sau nu se fac deloc update – uri.

Consistență – toate updat – urile acceptă constrângerile plasate pe toate elementele de date.

Izolarea – nici o tranzacție nu poate interfera cu activitățile sau update – urile unei alte tranzacții.

Durabilitate – tranzacțiile de succes sunt scrise pe media “durabile” (exp – disc magnetic) cât mai curând posibil.

Aceaste 4 puncte sunt cunoscute ca proprietățile ACID ale managementului tranzacției. Importanța proprietăților ACID pot fi înțelese ușor printr-un exemplu.

Să presupunem că ți-ai făcut plata lunară a cardului de credit și curând după asta mergi la un magazin din apropiere să faci alte cumpărături cu cardul tău. Să presupunem de asemenea că exact în momentul în care îti trece cardul peste un cititor magnetic, un funcționar de bancă îti face plata în baza de date a băncii. Fig. 8.18 ilustrează un mod în care un sistem de computer central ar putea procesa aceste tranzacții.

Fig. 8.18: Un scenariu de tranzacție

În figură, funcționarul de la bancă termină update-ul său înainte ca vânzătoa-rea să îl termine pe al său, lasându-te cu o balanță de 300$ neplătită. Tranzacția ar putea surveni la fel de ușor ca în Fig. 8.19, unde vânzătoarea termină prima update-ul, deci contul se termină cu balanța 0.00$, iar tu ți-ai făcut cumpărăturile pe gratis!

Fig. 8.19: Alt scenariu de tranzacție

Deși ești fericit că ai primit lucruri gratis, e la fel de probabil că ai putea să sfâșești plătinu-ți factura de 2 ori (sau să te cerți cu funcționarul de bancă până se corectează înregistrările).

Situația pe care tocmai am descris-o este numită condiție de întrecere pentru că starea finală a bazei de date nu depinde de corectitudinea updatărilor ci de care tranzacție se petrece ultima.

Managerii tranzacțiilor previn condițiile de întrecere prin introducerea atomicității și izolării. Fac asta plasând diferite tipuri de încuietori pe înregistrările de date. În exemplul nostru, în fig. 8.18, funcționarul de la bancă ar trebui să asigure o încuietoare “exclusivă” pe înregistrarea cărții de credit. Încuietoarea este înlăturată numai după ce balanța updatată este scrisă înapoi pe disc. În timp ce tranzacția funcționarului de bancă rulează, vânzătoarea primește un mesaj care spune că sistemul e ocupat. Când update-ul s-a terminat, managerul tranzacției îndepărtează încuietoarea și plasează alta imediat pentru vânzătoare. Tranzacția corectată este arătată în fig. 8.20

Fig. 8.20: O tranzacție atomică izolată

Există un risc în această abordare. De fiecare dată când o entitate este încuiată într-un sistem complex, există un potențial de impas. Sistemele pot manageria inteligent încuietorile pentru a reduce riscul impasului, dar fiecare măsură luată pentru a preveni sau detecta locurile de impas, plasează mai multe cheltuieli asupra sistemului. Cu prea mult management al încuietorilor, realizarea tranzacției suferă. În general, prevenirea impasurilor este secundară considerațiilor realizării. Situațiile de impas se întâmplă rar, în timp ce realizarea este un factor în fiecare tranzacție.

Un alt impediment în realizare este introducerea datelor. În timpul înregistrările updatării (care include ștergerea înregistrării) managrii tranzacțiilor bazelor de date scriu imaginile tranzacției într-un fișier jurnal. Astfel, fiecare updatare cere cel puțin două scrieri: una pe fișierul primar și un pe fișierul jurnal. Fișierul jurnal e important pentr că ajută sistemele să mențină integritatea tranzacției: dacă trebuie să se enunțe la tranzacție datorită unei erori. Dacă, de exp., sistemul de management al unei baze de date capturează o imagine a unei înregistrări fiind updatată înainte ca updatarea să fie făcută, această imagine veche poate fi repede scrisă înapoi pe disc, prin asta ștergând toate update-urile ultrioare updatărilor înregistrării. În unele sisteme, atât “înainte” cât și “după” ce imaginile sunt capturate, facând descoperirea erorilor relativ ușoară.

Jurnalele de baze de date sunt de asemenea folositoare ca urme de audit pentru a arăta cine a updatat care fișier la ce timp și exact ce date au fost schimbate. Unii administratori de sistem precauți păstrează aceste fișiere jurnal ani de zile în biblioteci de benzi.

Fișierele jurnal sunt unelte importante pentru recuperarea de date. Unele baze de date sunt pur și simplu prea mari pentru a fi puse pe bandă sau disc optic în fiecare seară – ia prea mult timp. În concluzie înregistrările bazelor de date se fac doar de două ori pe săptămână, dar fișierele jurnal sunt salvate în fiecare seară. Dacă dezastrul ar lovi vreodată într aceste înregistrări pline, ar putea fifolosite fișierele jurnal ale tranzacțiilor din celelate zile, reconstituind tranuacțiile fiecărei zile ca și cum ar fi reluate de utilizatori pe imaginile bazelor de date pline luate cu câteva zile mai devreme.

Accesul la baza de date controlează ce tocmai am discutat – securitate, managementul indexului și managementul încuietorilor – consumă resurse uriașe al sistemului. De fapt, această supraîncărcare era așa de mare pe sistemele mai vechi incât unii oameni au continut folosirea sistemelor bazate pe fișiere pentru că computerele lor gazdă nu puteau face față la încărcătura de date. Chiar și cu sistemele enorm de puternice de azi throughput – ul poate suferi sever dacă sistemul de baze de date nu e corespunzător menținut. Mediile de tranzacții cu volum mare sunt adeseafrecventate de programatorii de sisteme și analiștii de baze de date a căror singură sarcină e să păstreze sistemul la o performanță optimă.

8.7. Managerii de tranzacții

Un mod de a îmbunătăți performanța bazelor de date e pur și simplu să ceri bazelor de date să facă mai puțină treabă, mutând unele dintre funcțiile sale la alte componente de sistem. Managementul tranzacției este un component al bazei de date adesea porționat din funcțiile interne ale managementului de date ale unui sistem de management al bazei de date. Managerii tranzacțiilor care se susțin singure încorporează tipic balanța încărcăturii și alte caracteristici ale optimizării care sunt nepotrivite pentru includerea în softu intern al bazelor de date, îbunătățind astfel eficacitatea întregului sistem. Managerii tranzacției sunt folositori ăn particular când tranzacțiile în afaceri se întind peste două sau mai multe baze de date. Nici una din bazele de date participante nu poate fi responsabilă pentru integritatea bazelor de date egale dar un mnager de tranzacții extern le poate păstra pe toate.

Unul din cele mei vechi și mai pline de succes manager de tranzacții a fost Customer. Information and Control System (CICS) de la IBM CICS a fost folosit timp de 3 decade, venind pe piață în 1968. CICS merită notat pentru că a fost primul sistem care a integrat procesarea tranzacției (TP), managementul bazelor de date și managementul comunicațiilor în interiorul unei singure aplicații. Totuși, componentele CICS erau (și sunt încă) cuplate slab pentru a permite acordarea și managementul fiecărei componente, ca entitate separată. Componenta managementului comunicațiilor a CICS controlează acțiunile numite conversații între terminale și un sistem gazdă. Eliberat de poverile unui management de protocol bazele de date și programele de aplicații își fac traba mai eficient.

CICS a fost unul din sistemele de aplicații care a angajat chemăeri de procedură îndepărtată în interiorul unui mediu client – server. În încarnarea sa contemporană CICS poate manageria procese de tranzacție între mii de utilizatori de internet și mari sisteme gazdă dar chiar si astăzi, CICS seamănă foarte mult cu arhitectura sa din anii 1960, care a devenit paradigmă pentru fiecare sistem de procesare a tranzacțiilor care s-a inventat de atunci. Arhitectura modernă CICS e arătată schematic în fig. 8.21.

Fig. 8.21: Arhitectura CICS

După cum vedeți din diagramă, un program numit monitor de procesare a sistemului tranzacției (TP Monitor) este componentul pivot al sistemului. El acceptă input de la managerul telecomunicațiilor și autentifică tranzacțiile împotriva fișierelor de date conținând listele a ce utilizatorii sunt autorizați la care tranzacții – uneori această informație de securitate include informație specifică cum ar fi definirea căror locații pot rula anumite tranzacții (intranet vs internet de exemplu). Odată ce monitorul a autentificat tranzacția, el inițiază programul aplicației cerut de utilizator. Când e nevoie de date pentru aplicație, monitorul TP trimite o cerere la softul managerului bazei de date. Face totul mentinând atomicitatea și izolarea printre multe procese de aplicații concurente.

S-ar putea să gândești că nu ar trebui să fie motive pentru care toate aceste componente de soft TP să existe pe același computer gazdă. Într-adevăr nu există nici un motiv pentru a le păstra împreună. Unele arhitecturi distribuite dedică grupuri de servere mici monitoarelor TP care rulează. Aceste sisteme sunt fizic diferite de sistemele care conțin soft de management a bazelor de date. De asemenea nu e nevoie ca sistemele care rulează monitoarele TP să fie date. De exemplu ai putea avea sisteme SUnnic RISC pentru managementul comunicațiilor și Unisys ES/7000 care rulează softul bazelor de date sub sistemele de operare Data Center și Windows. Tranzacțiile ar fi intrate prin desktop sau PC – uri mobile. Această configzrație este cunoscută ca o arhitectură cu 3 nivele cu fiecare platformă reprezentând un nivel; cazul general fiind o arhitectură cu n nivele sau multinivel. Cu apariția webului și a comerțului electronic arhitecturile TP cu n nivele devin din ce în ce mai populare între vânzatori, incluzând Microsoft Netscape, Sybase, SAP AG și CICS de la IBM au avut succes în suportarea a variate sisteme de tranzacții cu n nivele. Desigur, e imposibil să spui care dintre acestea e “mai bun” pentru o anumită antrepiză fiecare având propiile avantaje și dezavantaje. Arhitectul de sisteme prudent păstrează în minte toate posturile și factorii pe care se bazează când concepe un sistem TP înainte de a decide care arhitectură are cel mai mult sens pentru orice mediu particular.

Rezumatul capitolului

Acest capitol a desrcris dependența mutuală a herdului și softului compute-rului. Softul de sistem lucrează împreună cu hardul de sistem pentru a crea un sistem funcțional și eficient. Softul de sistem incluzând sisteme de operare și softul de aplicații este o interfață între utilizator și hard, permițând arhitectura de nivel scăzut al computeruli să fie tratată abstract. Aceasta dă utilizatorilor un mediu în care ei sunt concentrați pe rezolvarea problemelor mai degrabă decât pe operațiile sistemului. Interacțiunea și adânca interdependență dintre soft și hard este mai evidentă în designul sistemelor de operare. În dezvoltarea lor istorică sistemele de operare au început cu o abordare “magazin deschis”, apoi au trecut la o abordare de grupuri conduse de operatori, apoi au evoluat la multiprogramare interactivă și calcul distribuit. Sistemele de operare moderne furnizează o interfață de utilizator modernă în plus față de alte servicii, incluzând managementul memoriei, managementul pro procesului, managementul resurselor generale, programare și protecție.

Cunoașterea conceptelor sistemelor de operare este critică pentru fiecare profesionist în computere. Virtual, toată activitatea de sistem se leagă înapoi de serviciile sistemului de operare. Când sistemele de operare clachează întregul sistem clachează. Ar trebui să realizezi totuși, au sau nu au nevoie de sisteme de operare. Acest lucru este în special adevărat în cazul sistemelor încastrate. Computerul din mașină sau microundele au sarcini atât de simple de îndeplinit, încât nu e necesar un sistem de operare. Totuși, pentru computerele care merg dincolo de sarcina simplistă de a rula un singur program, sistemele de operare sunt mandatare pentru eficiența și ușurința de utilizare. Sistemele de operare sunt unul din multele exemple de sisteme soft mari. Pentru aceste motive și multe altele, încurajăm o mai largă explorare a designului și dezvoltării sistemelor de operare. Asamblatorii și compilatorii furnizează mijloacele prin care limbajele de computer citibile de om sunt traduse în formă binară potrivită pentru executarea de un calculator. Interpreții produc de asemenea cod binar, dar codul în general nu e la fel de rapid sau eficient ca acela care este generat de un asamblator.

Limbajul de programare Java produce cod care este interpretat de o mașină virtuală situată între bytecodul său și sistemul de operare. Codul Java rulează mai încet decât programele binare, dar este portabil pentru o aranjare largă a platformei.

Softul sistemelor bazelor de date controlează accesul la fișierele de date, adesea prin serviciile unui sistem de procesare a tranzacțiilor. Proprietățile Acid ale unui sistem de baze de date asigură ca datele sunt întotdeauna într-o stare consistentă.

Construirea sistemelor mari este o provocare majoră cu care se confruntă astăzi știința computerelor. Până acum înțelegeți că un sistem de computer e mult mai mult decât hardul și programele. Sistemele de clasă ale antreprizelor sunt agregări de procese interdependente, fiecare cu scopul său propriu. Eșecul sau slaba performanță vor avea un efect de pagube asupra întregului sistem – sau măcar în percepția utilizatorilor săi. Pe măsură ce continuați în cariera și educația voastră, veți studia multe din topicurile acestui capitol mai în detaliu. Dacă ești administrator de sisteme sau programator de sisteme, vei stăpâni aceste idei pe măsură ce ele se aplică în contextul unui mediu particular de operare.

Nu contează cât de inteligenți suntem în scrierea programelor, puține putem face pentru a compensa slaba performanță a oriăreia din componentele sistemelor pe care se bazează programele noastre. Te invităm să cercetezi în capitolul 10, unde prezentăm unu studiu mai detaliat al punctelor performanțelor sistemelor.

Citire înaintată

Cel mai interesant material în zona softului de sistem este cel care însoțește produsele unui anumit vânzător. De fapt, poți adesea judeca calitatea produsului unui vânzător după calitatea și grija pe care o acordă pregătirii documentației. O vizită la site-ul web al vânzătorului, te poate recompensa uneori cu o reprezentare la prima mână a bazelor teoretice pentru produsele lor. Doi dintre cei mai buni vânzători de web – siteuri la această scriere sunt aceia ai IBM și Sun: www. Software.IBM.com și www. Java. Sun.com. Dacă perseverezi fără îndoială vei găsi și altele. Cartea lui hall (1994) despre sisteme client – server oferă o excelentă introducere în teoria client – server. Exploră un număr de produse care erau populare când a fost scrisă cartea. Stallings (2001), Tanembaum (1997), și Silberschatz, Galvin, și Gagne (2001) toți oferă o acoperire excelentă a conceptelor sistemelor de operare introduse în acest capitol precum și subicte mai avansate. Stallings include exemple detaliate de diferite sisteme de operare și relația lor cu hardul actual al mulțimii. O relatare asupra dezvoltării OS/360 poate fi găsită în Brooks (1995).

Cartea lui Grosline (1988) desprea asamblare oferă una di cele mai bune tratări asupra modului de funcționare al asamblatorilor. De asemenea intră în detaliile legării și macroasamblării. Aho, Sethi și Ullman (1986) au scris cartea “definitivă” despre compilatori. Numită adesea “Cartea Dragon” datorită ilustrației de pe copertă, a rămas la tipar de aproape două decenii datorită teoriei sale clare despre compilatori. Chiar și oamenii de știință serioși în calculatoare ar trebui să aibă în apropiere această carte. Sun Microsystems este sursa primară pentru orice are legătură cu limbajul Java, Addison – Weley publică o serie de cărți detaliind punctele cele mai fine ale Java. Specificarea Mașinii Virtuale Java de Lindholm și Yellin (1999) este una dintre cărțile din această serie.

Te va informa despre unele din trăsăturile construcției de fișiere clasă peste care am trecut în acest material introductiv. Cartea lui Lindholm și Yellin include și o listare completă a instrcțiunilor bytecode Java, cu echivalenții lor binari.

Un studiu atent al acestei lucrări îți va da o nouă perspectivă asupra limbajului.

Deși puțin depășită (1993) cartea lui Gray și Reuter despre procesarea tranzacțiilor este ușoară de citit și poate fi ușor înțeleasă. Îți va da o bună fundație pentru un studiu mai aprofundat în această zonă. O tratare înalt abordată a teoriei a bazelor de date și aplicațiilor poate fi găsită în Silberschatz, Korth, și Sudarshan (2001).

Referințe :

Recapitularea conceptelor și termenilor esențiali

Care era principalul obiectiv al primelor sisteme de operare prin comparație cu obiectivele sistemelor de azi ?

Ce îmbunătățiri la operațiile computerului au fost aduse de monitoarele rezidente ?

Cu privire la outputul imprimantei, cum s-a obținut cuvântul “rulare” (SPOOL) ?

Descrie cum diferă sistemele multiprogramare de sistemele împărțire a timpului

Care este cel mai critic factor în operarea sistemelor grele timp real ?

Sistemele multiprocesor pot fi clasificate după felul în care comunică. Cum sunt ele clasificate în acest capitol ?

În ce mod e diferit un sistem de operare distribuit de un sistem de operare rețea ?

Ce se întelege prin transparență ?

Descrie cele două filosofii divergente asupra designului nucleului sistemelor de operare

Care sunt beneficiile și pierderile la o interfață a sistemelor de operare EUI ?

Cum e diferită planificarea procesării pe termen lung de planificarea procesării pe termen scurt ?

Ce se întelege prin planificarea prioritară ?

Care metodă în planificarea procesului este mai utilă în mediul de împărțire al timpului ?

Care metodă de planificare a procesului este optimă demonstrabil ?

Descrie pașii implicați în realizarea unei comutări de context

Pe lângă managementul procesului care sunt celelalte două funcții importante ale unui sistem de operare ?

Ce este un suprastrat ? De ce nu mai e nevoie de suprastraturi în sisteme mari de computere ?

Sistemele de operare și un program utilizator au două percepții diferite asupra unei Mașini Virtuale. Explică modul în care diferă

Care este diferența între un subsistem și o partiție logică ?

Numește câteva avantaje ale consolidării serverului. Consolidarea serverului e o idee bună pentru orice antrepriză ?

Descrie ierarhia limbajului de performare. De ce este un triunghi simbolul potrivit pentru reprezentarea acestei ierarhii ?

Cum diferă un cod absolut de un cod relocalizabil ?

Care e scopul unui editor de linkuri. Prin ce e diferit de o bibliotecă de linkuri dinamice ?

Descrie scopul fiecărei faze a unui compiler

Prin ce diferă un interpret de un compilator ?

Care este trăsătura izbitoare a limbajului de programare Java care susține portabilitatea sa asupra mediilor hardware disparate ?

Asamblatorii produc cod mașină care este executabil după ce a fost link- editat. Compilatorii Java produc _______________ care este interpretat în timpul execuției

Care este un număr magic care identifică un fișier de clasă Java

Prin ce e diferită o schemă logică de baze de date de o schemă fizică de o baze de date ?

Care structură de date e mai comun utilizată pentru bazele de date index?

De ce sunt necesare reorganizările bazelor de date ?

Explicați proprietățile ACID ale unui sistem de baze de date.

Ce este o condiție de categorie ?

Intrările bazelor de date servesc dou scopuri. Care sunt ele ?

Ce servicii furnizează managerii de tranzacții ?

Exerciții

Care simțiți că sunt limitările unui computer care nu are sistem de operare ? Cum ar încărca sau executa un program utilizatorul ?

Microundele încerarcă să ofere un nucleu cât de mic posibil, punând mult din suportul sistemului de operaere în module adiționale. Care simți că sunt serviciile minime pe care trebuie să le ofere nucleele ?

Dacă ai scrie un cod pentru un sistem de operare de timp real ce restricții ai dori să impui sistemului ?

Care este diferența între multiprogramare și multiprocesare. Multiprogramare și multifir ?

Sugestii și răspunsuri:În ce circumstanțe e de dorit să colectezi grupuri de procese și programe în subsisteme care rulează pe un computer mare ?

Ce avantaje ar exista să folosești atât subsistemele cât și partițiile logice pe aceeași mașină ?

Sugestii și răspunsuri: Când e potrivit să folosești cod de program binar nerelocalizabil ? De ce e prferat codul relocalizabil ?

Să presupunem că nu există un asemenea cod de program relocalizabil. Cum ar fi făcut mai complex procesul paginării mamoriei ?

Sugestii și răspunsuri: Discutați avantajele și dezavantajele legării dinamice

Ce probleme are un asamblator de depășit pentru a produce cid binar complet într – o singură trecere peste fișierul sursă ? Cum ar putea fi diferit codul scris de un asamblator o trecere de codul scris pentru un asamblator două treceri ?

De ce ar trebui să fie evitat limbajul de asamblare pentru dezvoltarea aplicației generale ? Sub ce circumstanțe este preferat sau cerut limbajul de asamblare ?

Sub ce circumstanțe ai argumenta în favoarea folosirii codului limbaj de asamblare pentru dezvoltarea unui program de aplicație ?

Care sunt avantajele folosirii unui limbaj compilat față de unul interpretat ? În ce circumstanțe ai alege un limbaj interpretat ?

Discută următoarele întrebări referitoare la compilatori:

care fază a unui compilator ți-ar da o eroare de sintaxă ?

care fază se plânge de variabile nedefinite ?

dacă încerci să adaugi un nr. unui caracter ce fază a compilatorului ar emite mesajul de eroare ?

De ce este mediul de execuție de clasă Java numit Mașină Virtuală ? Cum se compară această mașină virtuală cu o mașină reală care rulează cod scris în C ?

De ce presupui că aria de metodă a unei JVM este globală asupra tuturor firelor care rulează în mediul mașinii virtuale ?

Am stabilit că doar o singură metodă într-un anumit timp poate fi activă în interiorul fiecărui fir care rulează în JVM. De ce crezi că acesta este cazul ?

Bytecodul Java pentru acces la ordinea variabilei locale pentru o clasă e de cel mult 2 biți. 1 bit e folosit pentru opcade, celălalt indică poziția în ordine. Câte variabile pot fi țiunute în ordinea variabilelor locale ?. Ce crezi că se întâmplă când e depășit acest număr ?

Sugestii și răspunsuri: Java e numit limbaj interpretat, totuși Java e un limbaj compilat care produce un șuvoi de output binar. Explică modul în care acest limbaj poate fi atât compilat cât și interpretat

Am spus că performanța unui program Java care rulează în JVM nu se poate potrivi cu cea a unui limbaj compilat obișnuit. Explică de ce ?

Răspunde la următoarele cu referire la procesarea bazelor de date:

a) Sugestii și răspunsuri: Ce e o condiție de prioritate ? Dă un exemplu

b) Sugestii și răspunsuri: Cum pot fi prevenite condițiile de prioritate ?

c) Sugestii și răspunsuri: Care sunt riscurile în prevenirea condițiilor de prioritate ?

22. În ce feluri sunt superioare arhitecturile procesării tranzacțiilor pe n ranguri sperioare arhitecturii pe un segment rang ? De obicei care costă mai mult ?

23. Pentru a îmbunătății performanța, compania ta a decis să replice baza sa de date despre prodeuse peste câteva servere, deci nu toate tranzacțiile trec printr-un singur sistem. Ce tipuri de probleme e nevoie să iei în considerare ?

24. Am spus că riscul impasului e întotdeauna prezent în orice moment e blocată resursa unui sistem. Descrie un mod în care poată să apară impasul

25. Caută diferite interfețe de linie de comandă (ca Unix, MS – DOS, și VMS) și diferite interfețe Windows (ca orice produs Microsoft Windows, MacOS, și KDE).

a) Să considerăm unele dintre comenzile mjore cum ar fi listarea unui director, ștergerea unui fișier sau schimbarea directorilor. Explicați cum e implementată fiecare din aceste comenzi pe diferite sisteme de operare studiate.

b) Listați și explicați unele din comenzile care sunt mai ușoare folosind o interfață linie de comandă vs folosirea unui GUI, un GUI vs folosirea o interfață linie de comandă.

c) Ce tip de intefață preferi ? De ce ?

Similar Posts