CUPRINS
Capitolul 1– Istoria sistemelor de operare 2
1.1. Primul calculator 2
1.2. Prima generaţie 2
1.3 Generaţia a II-a 2
1.4. Generaţia a III-a 4
1.5 Generaţia a IV-a 5
Capitolul 2 – Concepte de bază 6
2.1 Procedură, subrutină sau funcţie 6
2.2 Introducere în cadrul subrutinelor 8
2.3 Noţiuni generale cu privire la subrutine 8
2.4 Avantaje şi dezavantaje ale subrutinelor 9
2.5 Procedurile stocate 10
2.5 Avantajele si dezavantajele procedurilor stocate 10
Capitolul 3 – Corutinele 13
3.1 Corutine sau subrutine? 13
3.2 Comparaţie detaliată 14
3.3 Corutine şi generatori 14
3.4 Utilizări generale ale corutinelor 15
3.5 Alternative şi implementări de corutine 16
Capitolul 4 – Subrutine în Matlab 17
Capitolul 5 – Optimizarea apelurilor în subrutine 21
5. 1. Introducere 21
5. 2. Optimizări fără restricţii. Minimalizarea unei funcţii scalare 21
5. 3. Optimizări fără restricţii. Minimalizarea unei funcţii vectoriale de normă L2 22
5. 4. Optimizări fără restricţii. Minimalizarea unei funcţii vectoriale de normă L1 23
5. 5. Optimizări fără restricţii. Minimalizarea unei funcţii vectoriale de normă L∞ 24
5. 6. Optimizări cu restricţii. Minimalizarea unei funcţii scalare 25
5. 7. Optimizări cu restricţii. Minimalizarea unei funcţii vectoriale de normă L1 26
5. 8. Optimizări cu restricţii. Minimalizarea unei funcţii vectoriale de normă L∞ 27
5. 9. Exemple de optimizare non-liniară 28
Capitolul 6 – MPI(Message Passing Interface) – Interfaţa Transferului de Mesaje 29
6.1. Formatul apelurilor MPI 30
6.2. Structura generală a programelor MPI 30
6.3. Rutinele de administrare a mediului MPI 31
6.4. Concepte generale despre rutinele de tipul punct-la-punct 33
6.5. Rutine de blocare a transferului de mesaje 34
6.6. Rutine de anti-blocare a transferului de mesaje 36
6.7. Iniţializarea variabilelor în limbajul de programare “FORTRAN” 38
6.8. Despre expresia “mod” 39
6.9. Reîntoarcerea (în Subrutine) 40
6.10. Substituirea variabilelor în subprogram 40
Capitolul 7 – Ce reprezintă RPC? 42
7.1. Ce este RPC? 42
7.2. Cum funcţionează RPC ? 42
7.3. Privire de ansamblu la rutinele de interfaţă 43
Capitolul 8 – Comunicare între procese – sincronizare, interblocaje 45
8.1. Ce este un proces? 45
8.2. Comunicarea prin partajarea memoriei 47
8.3. Comunicarea prin transfer de mesaje 48
8.4. Comunicare în sistem client-server 49
8.5. Probleme clasice ale comunicării interprocese 53
8.5.1. Problema filozofilor care mănâncă 53
8.5.2. Problemele cititorilor şi scriitorilor 55
8.5.3 Problema frizerului somnoros 56
BIBLIOGRAFIE 58
1. Istoria Sistemelor de Operare
1.1 Primul calculator
Istoria sistemelor de operare se împleteşte cu istoria calculatoarelor (hardware-ului).
Primul calculator numeric: A fost ”motorul analitic” al lui Charles Babbage (matematician englez, 1792 -1871). Acesta era mecanic. Nu a funcţionat niciodată corect, deoarece tehnologia acelor vremuri nu permitea construirea unor roţi dinţate suficient de precise.
Nu avea sistem de operare, dar Babbage a intuit necesitatea existenţei unor programe pentru motorul analitic, motiv pentru care a angajat-o pe Ada Lovelace (fiica poetului englez lord Byron) ca prima programatoare din lume - după numele ei a fost denumit limbajul de programare ADA.
1.2 Prima generaţie
Prima generaţie (1945 - 1955) - tuburi electronice şi plăci de conexiuni: Pe la jumătatea anilor ’40 Howard Aiken (Harvard), John von Neumann (institutul de studii avansate din Princetown), J. Presper Eckert, William Mauchley (Univ. Pennsylvania) şi Konrad Zuse (Germania) au reuşit construirea calculatoarelor cu relee, apoi cu tuburi electronice - erau foarte mari (ocupau mai multe camere), dar erau de milioane de ori mai lente decât un calculator ieftin de azi.
Acelaşi grup de oameni proiectau, construiau, programau, operau şi menţineau în funcţiune propria maşină. Programarea se realiza în limbaj maşină absolut, prin inserarea de plăci de conexiuni realizate cu fire. Ulterior (începutul anilor ’50) s-au folosit cartele perforate.
Nu existau limbaje de programare (nici măcar limbaje de asamblare), nici sisteme de operare. Problemele rezolvate erau în general calcule simple (de exemplu: tabele de sin, cos,logaritmi).
1.3 Generaţia a II-a
Generaţia a II-a (1955 - 1965) - tranzistoare şi prelucrare pe loturi: Odată cu introducerea tranzistoarelor (jumătatea anilor ’50) calculatoarele au devenit suficient de fiabile ca să fie fabricate şi vândute unor clienţi. Practic, a început să se facă distincţie între proiectanţi, constructori, programatori,personalul de întreţinere. Maşinile, numite mainframe (sisteme mari de calcul) erau puse în camere speciale, cu aer condiţionat şi erau manevrate de operatori calificaţi. Erau scumpe (milioane de dolari) şi nu şi le puteau permite decît marile corporaţii, agenţii guvernamentale, universităţile.
Lucrul era organizat pe job-uri (job = program sau grup de programe). Programatorul scria programul pe hârtie, apoi pe cartele perforate, dădea pachetul operatorului, apoi aştepta rezultatele. Operatorul lua pachetul, îl introducea în calculator, apoi lua de la imprimantă listing-ul cu rezultatele şi le preda programatorului. Procesul continua în acelaşi mod şi cu alte pachete. Dacă era nevoie de un anumit compilator, îl lua din dulap şi îl transfera prin citire în calculator. Astfel, operatorii făceau multe drumuri prin camerele din jurul maşinii şi se pierdea timp.
Pentru a se câstiga timp s-a trecut la prelucrarea pe loturi de programe: în alte camere mai multe job-uri erau transferate de pe cartele pe o banda magnetică cu un calculator ieftin (IBM 1401), apoi banda era dusă la calculatorul principal (IBM 7094) împreună cu un strămoş al sistemelor de operare de astăzi (care citea succesiv job-urile de pe bandă şi le rula), rezultatele erau scrise pe altă bandă, care era dusă mai apoi la calculatorul ieftin pentru tipărire la imprimanta.
Structura unui job (pe cartele):
$JOB durata maximă de rulare, cont, nume programator
$FORTRAN − cere sistemului de operare să încarce compilatorul de FORTRAN de pe banda sistem
− programul în FORTRAN (va fi compilat şi salvat pe benzi auxiliare):
$LOAD − cere sistemului de operare să încarce programul obiect proaspăt compilat
$RUN − cere sistemului de operare să ruleze programul
− date pentru program:
$END − sfârşitul programului
Astfel, se lucra neinteractiv, introducând deodată, la inceput, pachetul de cartele conţinând atât programul, cât şi datele şi comenzile sistemelor de operare. Limbajele de programare folosite frecvent erau FORTRAN şi limbajul de asamblare. Sistemele de operare tipice erau FMS (FORTRAN Monitor System), IBSYS (Sistem de operare de la IBM pentru calculatorul IBM 7094). Problemele rezolvate erau de obicei calcule ştiinţifice şi inginereşti, ca de exemplu: rezolvarea ecuaţiilor diferenţiale şi cu derivate parţiale.
1.4 Generaţia a III-a
Generaţia a III-a (1965 - 1980) - circuite integrate şi multiprogramare: Circuitele integrate au permis îmbunătăţirea raportului performanţă/preţ. Prima serie de calculatoare cu circuite integrate a fost IMB 360 - o familie de maşini diferite ca performanţă şi preţ, dar compatibile software. Pentru ele a fost scris sistemul de operare OS/360. Acesta a avut multe probleme de funcţionare, a cunoscut multe versiuni, deoarece era greu de scris un sistem de operare adecvat pentru diversele caracteristici şi scopuri ale maşinilor din seria 360, să lucreze eficient şi cu periferice multe, dar şi cu periferice puţine,atât în medii comerciale cât şi în medii ştiinţifice. Avea câteva milioane de instrucţiuni.
Noutăţi introduse de OS/360:
-
multiprogramarea: la IBM 7094, când job-ul curent făcea o pauză aşteptând ca banda sau alt dispozitiv de I/O să-şi termine activitatea, unitatea centrală (UCP) era neutilizată. Soluţia a fost partajarea memoriei în mai multe zone, încărcarea câte unui program în fiecare partiţie, iar când o lucrare aştepta terminarea activităţii unui dispozitiv de I/O, o altă lucrare putea utiliza UCP. Prezenţa simultană a mai multor lucrări în memorie a impus şi existenţa unui modul hardware care să protejeze fiecare program de a fi spionat sau modificat de celelalte.Maşinile seriei 360, precum şi altele din generaţia a III-a, aveau un asemenea modul.
-
posibilitatea de a transfera programele de pe cartele, pe disc imediat ce erau aduse în camera calculatorului: când un program se termina de executat, sistemul de operare încărca altul nou de pe disc în zona de memorie rămasă liberă şi apoi îl executa. Această tehnică se numeşte virtualizare („spooling” – Simultaneous Peripheral Operation On Line = operare simultană online a perifericelor) şi era folosită şi pentru ieşire. Folosind virtualizarea, maşinile auxiliare (IBM 1401) nu au mai fost necesare, iar plimbatul benzilor a dispărut. Deşi sistemele de operare din generaţia a III-a erau potrivite pentru calcule ştiinţifice complicate sau prelucrarea unor cantităţi mari de date comerciale, ele rămâneau sisteme de prelucrare pe loturi de programe. Dorinţa de a avea un timp redus de răspuns a determinat apariţia partajării în timp (timesharing), o variantă de multiprogramare, în care fiecare utilizator are un terminal online - dacă sunt 20 de utilizatori conectaţi şi 17 se aşteaptă, UCP este distribuită pe rând celor 3 job-uri care solicită serviciul. Primul sistem de operare cu partajare în timp a fost CTSS (Compatibile Time Sharing System), dezvoltat de M.I.T. pe o maşină 7094 adaptată. Partajarea în timp a devenit însă populară abia după introducerea unui modul hardware pentru protecţie.
CTSS a avut însă succes, ceea ce a determinat M.I.T., Bell Labs şi General Electric să dezvolte MULTICS (MULTiplexed Information and Computing Service - serviciu multiplexat pentru calcule şi informaţii) - el a fost proiectat să deservească o maşină cu un număr mare de dispozitive de I/O. MULTICS a introdus multe idei de perspectivă şi a condus, ulterior, la realizarea sistemului UNIX, devenit popular în lumea academică, agenţii guvernamentale şi diverse companii.
Diverse organizaţii şi-au creat propriile versiuni de UNIX (de exemplu: System V (de la AT&T), BSD (Berkeley Soft Distribution),HP-UX). De aceea, IEEE a dezvoltat un standard pentru UNIX numit POSIX care defineşte o interfaţă minimală de apeluri sistem şi care pot fi portate uşor de la un sistem de calcul la altul. În prezent şi alte sisteme de operare suportă interfaţa POSIX.
În 1987, A.S. Tanenbaum a lansat MINIX, o clonă redusă de UNIX, gratuită, pentru scopuri educaţionale. Dorinţa de a realiza o versiune de MINIX, tot gratuită, dar pentru scopuri de producţie, l-a determinat pe Linus Torvalds să realizeze Linux. Tot în cadrul generaţiei a III-a, s-a manifestat şi evoluţia fenomenală a minicalculatoarelor, ca DEC PDP-1, ..., PDP-11 (incompatibile cu familia IBM). Ele erau tot mari, dar mai accesibile şi acum fiecare departament al unei instituţii putea avea propriul său minicalculator.
1.5 Generaţia a IV-a
Generaţia a IV-a (1980 - prezent) - calculatoare personale: Calculatoarele personale au apărut datorită dezvoltării circuitelor integrate LSI (Large Scale Integration) - puteau conţine mii de tranzistori pe cm2. Erau asemănătoare ca arhitectură cu minicalculatoarele PDP-11, dar mai ieftine. Astfel, era posibil ca fiecare utilizator să aibă propriul calculator (nu doar departamentele).
Sistemele de operare folosite la început au fost:
- CP/M (Control Program for Microcomputer) - pentru procesoare 8080 (introduse de Intel în 1974), Z80 (de la Zilog)
- MS-DOS pentru IBM-PC (calculator introdus de IBM în 1981), realizat de Microsoft, preluând anumite idei din UNIX într-o formă foarte simplistă.
Piaţa procesoarelor a fost din ce în ce mai dominată de familiile (compatibile) Intel (286, 386, 486, Pentium-urile) şi AMD.Pentru calculatoarele personale, cele mai folosite sisteme de operare sunt:
- familia Windows, care a preluat idei de interfaţă prietenoasă de la sistemele de operare pentru calculatoarele Apple Macintosh (care oferă o interfaţă grafică având cu pictograme, lucru cu mouse).Versiunile până la 3.11 erau doar medii de programare, aplicaţii ce se lansau din MS-DOS şi ofereau o interfaţă prietenoasă pentru utilizator şi cu mai multe facilităţi pentru rularea programelor. Începând de la Windows 95 (98, NT, 2000, Me, XP, Vista) acestea au devenit sisteme de operare.
- familiile UNIX (comerciale) şi Linux (gratuite).În practică, sistemele Windows sunt folosite extensiv pentru utilizare casnică şi amuzament, iar sistemele UNIX/Linux, pentru servere.
Deşi în decursul evoluţiei calculatoarelor s-a manifestat o tendinţă de miniaturizare şi utilizare la nivel din ce în ce mai restrâns (până la nivel personal), în prezent există o tendinţă de reapariţie a mainframe-urilor, ca servere pentru Internet, pentru comerţ electronic. Acestea conţin tot software-ul necesar, iar utilizatorii se pot conecta la ele cu un calculator slab şi o conexiune la Internet bună, având doar rol de terminal. Un exemplu este proiectul Google de a crea un sistem de operare online (GooOS), ce presupune ca pe un calculator foarte puternic să se creeze un sistem în care orice om de pe planetă să poată avea propriul cont. Sistemul găzduieşte fişierele utilizatorului şi conţine tot software-ul necesar, iar maşina de unde operează utilizatorul este doar un simplu terminal. Această tendinţă se explică prin faptul că tot mai mulţi utilizatori vor să poată utiliza calculatorul uşor şi repede, fără a fi nevoiţi să înveţe toate cunoştinţele necesare administrării unui sistem complex ,administrarea fiind lăsată pe seama profesioniştilor.
2.Concepte de bază
2.1 Procedură, subrutina sau funcţie
Pentru început, se vor evalua două paradigme diferite de programare:
-
Programarea procedurală
-
Programarea orientată pe obiecte
Cea mai importantă deosebire între aceste două tehnici de programare este aceea că programarea procedurală tratează fiecare program ca pe o listă de instrucţiuni ce va fi citită de sus în jos, în timp ce programarea obiect orientată (POO) se bazează pe interacţiunea diferitelor obiecte pentru a obţine obiectivul programului.
Fiecare obiect, în termeni de POO, poate fi compus din cod procedural, iar anumite programe procedurale pot fi descompuse în module, ceea ce dă sens ideii că ar fi cumva obiect orientate.
Din punct de vedere istoric, primele programe au fost integral procedurale. S-au introdus mecanisme pentru a permite interpretorului programelor să se deplaseze în cod (salturi jump), dar nu există un consens al independenţei între blocurile de cod. Limbaje precum C++ au introdus mecanisme (clasa) care au permis orientarea pe obiecte, dar segmentele de cod individuale erau încă procedurale prin natură.
SUBRUTINA
O subrutină este o secvenţă de cod executată la cerere, separată de fluxul principal al programului. Interpretorul va sări la acel cod, îl va executa şi va returna programului principal. Cuvinte cheie, precum GOSUB sau RETURN, din limbajul BASIC, adesea folosite cu numere de linie, au permis o modalitate prietenoasă pentru programator de a face acest lucru. Echivalentele în limbajul de asamblare erau mai greu de utilizat, de obicei cuprinzând o comparaţie, salt (jump) şi returnare (return), completate cu offset-uri, adrese de memorie şi/sau etichete.
Subrutinele sunt considerate de mulţi ca fiind greu de întreţinut, dificil de citit şi utilizat, rezervate pentru uz atunci când nimic altceva nu merge (precum instrucţiunea GOTO). Trebuie menţionat faptul că în limbajele de programare moderne, ce implementează o structură modulară, cu etichete cu nume în locul numerelor de linie, se pot include subrutinele ca o modalitate acceptabilă de lucru. Totuşi, având în vedere existenţa funcţiilor şi a procedurilor, această tehnică este foarte rar utilizată.
Generic, termenul de subrutină poate denota o secvenţă dintr-un cod, separată de corpul principal, ce îndeplineşte o operaţiune discretă, în termeni neutri din punct de vedere al limbajului. De exemplu, un document se poate referi la aşa-numitele subrutine de tratare a fişierelor.
PROCEDURA
O procedură reprezintă numele unui bloc dintr-un cod, la fel ca o subrutină, dar cu facilităţi suplimentare. De exemplu, poate accepta parametri, ce pot fi intrări, ieşiri sau de trecere (pass-through). Tradiţional, o procedură care returnează valori s-a numit funcţie, nume pe care multe limbaje de programare moderne îl folosesc pentru toate blocurile de cod ce poartă nume.
Astfel, cuvântul cheie PROCEDURE există doar în câteva limbaje de programare şi a dispărut din multe altele. Limbajul C nu îl foloseşte, limbajele BASIC îl foloseşte, iar limbajele Modula şi Pascal au atât PROCEDURE, cât şi FUNCTION ca şi cuvinte cheie (FUNCTION este o PROCEDURE care returnează o valoare).
FUNCŢIA
Aşa cum s-a arătat, o funcţie este considerată în anumite limbaje ca fiind o procedură care returnează o valoare. Totuşi, este de obicei termenul folosit pentru a referi orice bloc cu cod ce poartă un nume. De notat că limbajele bazate pe C folosesc exclusiv cuvântul de cod function.
Funcţiile acceptă parametri, returnează valori şi sunt ţinute de obicei separat de codul programului principal. Multe limbaje de programare au o funcţie specială (în C, funcţia main) desemnată ca punct de intrare a unui program. Limbajele bazate pe BASIC nu au asemenea puncte de intrare, deoarece sunt exclusiv procedurale, adică execuţia începe din partea de sus a programului şi continuă până când i se spune să se oprească.
METODA
Pe scurt, o metodă este o funcţie conţinută într-un obiect. În termeni de POO, se vorbeşte întotdeauna despre obiecte, metodele şi proprietăţile lor. Fiecare metodă este o acţiune pe care i-o putem cere obiectului să o realizeze pe una sau mai multe dintre proprietăţile lui.
2.2 Introducere în cadrul subrutinelor
În programare, o subrutină (numită şi procedură, metodă, funcţie, sau rutină) este o porţiune de cod din cadrul unui program mai mare, care îndeplineşte o sarcină specifică (task) şi este relativ independent de restul codului. După cum numele de "subprogram" sugerează, o subrutină se comportă aproximativ în acelaşi fel ca şi un program, care este de fapt un pas într-un program mai mare sau într-un alt subprogram. O subrutină este adesea codificată astfel încât să poată fi apelată de mai multe ori şi/sau din mai multe locuri în timpul unei singure execuţii a programului, inclusiv din alte subrutine şi apoi să fie trimisă înapoi (return) la instrucţiunea următoare după ce apelul sarcinii subrutinei este încheiat. Subrutinele reprezintă un instrument puternic de programare şi sintaxa multor limbaje de programare include suport pentru scrierea şi utilizarea lor. Folosirea ratională a subrutinelor (de exemplu, prin abordarea programării structurate) deseori va reduce, în mod substanţial, costurile dezvoltării şi menţinerii unui program mare, crescând în acelaşi timp calitatea şi fiabilitatea. Subrutinele, adesea colectate în biblioteci, sunt un mecanism important pentru schimbul de informaţii şi pentru software-ul comercial. Disciplina programării orientate pe obiect este bazată pe obiecte şi metode (subrutine care sunt anexate la aceste obiecte sau la clasele obiect). În tehnica de compilare numită “cod filetat”(threaded code), programul executabil este de fapt o secvenţă a apelurilor subrutinei.
2.3 Noţiuni generale cu privire la subrutine
Conţinutul unei subrutine este de fapt corpul său (body), partea de cod a programului care este executată atunci când subrutina este apelată. O subrutină poate fi scrisă astfel încât să se aştepte obţinerea a una sau mai multe valori de date după apelarea programului ( parametrii săi). Aceasta, de asemenea, poate întoarce o valoare calculată apelantului său (valoare returnată), sau poate furniza diferite valori rezultate sau parametri de ieşire(“output parameters”). Într-adevăr, o utilizare des întâlnită a subrutinelor este de a implementa funcţii matematice, în care scopul lor principal este pur si simplu de a calcula unul sau mai multe rezultate ale căror valori sunt în întregime determinate de parametrii găsiţi în subrutină (Exemple: calculul logaritmului unui număr sau determinantul unei matrice). Cu toate acestea, un apel de subrutină poate avea şi efecte adverse, cum ar fi modificarea structurilor de date în memoria calculatorului, citirea din sau scrierea într-un dispozitiv periferic, crearea unui fişier, oprirea programului sau a maşinii de calcul, sau chiar întârzierea execuţiei programului pentru un anumit timp. Un subprogram cu efecte adverse poate returna rezultate diferite de fiecare dată când este apelat, chiar dacă este apelat cu aceiaşi parametri. Utilizarea pe scară largă a subrutinelor cu efecte secundare este o caracteristică a limbajelor de programare obligatorii. O subrutină poate fi codificată astfel încât să se poată apela recursiv, în vederea îndeplinirii sarcinilor sale. Această tehnică permite punerea în aplicare directă a funcţiilor definite prin inducţie matematică şi prin algoritmi recursivi de tip “divide et impera”.
O subrutină al cărei scop este de a calcula o singură funcţie de valoare booleană (adevarat sau fals) este numită afirmaţie (“predicate”).
2.4 Avantaje şi dezavantaje ale subrutinelor
Avantajele împărţirii unui program în subrutine includ:
-
reducerea copiilor de cod în cadrul unui program
-
permiterea reutilizării codului în programe multiple
-
descompunerea unor sarcini complexe de programare în paşi mai simpli
-
împărţirea unei sarcini mari de programare între programatori diferiţi, sau diferite etape ale unui proiect
-
ascunderea detaliilor de implementare de utilizatorii subrutinei.
Dezavantajele acestora sunt:
-
Apelarea unei subrutine (mai degrabă decât folosind linii de cod) impune cheltuieli suplimentare de calcul în cadrul mecanismului de apel în sine
-
Subrutina necesită de obicei cod standard de menaj - atât la intrare ,cât şi la ieşire, funcţia, salvând, de obicei, registre de uz general şi returnând adresa ca cerinţă minimă)
2.5 Procedurile stocate
Reprezintă acele programe care se execută direct pe server-ul de baze de date ,eliberând astfel o mare parte din traficul în reţea şi folosind resursele ceva mai puternice ale serverului. Una dintre modificările aduse de SQL99 a fost introducerea unui capitol destinat procedurilor stocate, denumit SQL/Persistent Stored Modules (SQL/PSM). Procedurile stocate asigură standardului SQL posibilitatea realizării unei prelucrări procedural complete. Aceste procedure stocate pot fi scrise în limbaje ce respectă mai mult sau mai puţin standardul SQL (PL/SQL-Oracle, SQL Procedures language-DB2 IBM, Microsoft SQL Server) sau în alte limbaje de programare generalizate (Ada, C, C++, Fortran, Pascal sau Java). În orice limbaj ar fi implementate, ele conţin pe lângă comenzi de interogare sau manipulare a datelor şi comenzi destinate controlului execuţiei, în aşa fel încât cu ele să poată fi implementată cea mai mare parte a logicii economice a aplicatiilor.
SQL PSM asigură constructori sintactici şi semantici pentru specificarea modulelor stocate, procedurilor şi funcţiilor. Rutinele stocate pot fi apelate din orice trazacţie SQL din interiorul sau din exteriorul sistemului.
Dostları ilə paylaş: |