Biologie | Chimie | Didactica | Fizica | Geografie | Informatica | |
Istorie | Literatura | Matematica | Psihologie |
A. INTRODUCERE IN UNIX
1.PREZENTAREA SISTEMULUI UNIX
Sistemul UNIX a fost apreciat inca de la conceperea sa in 1969 , intrucat putea sa ruleze pe masini cu diferite puteri de procesare, de la microprocesoare pana la mainframe-uri, si asigura un mediu comun de procesare. Sistemul cuprinde doua parti:
programe si servicii: Shell, porti electronice, editoare de texte si sisteme de control al codului sursa;
sistemul de operare (propriu-zis) care este suportul acestor programe si servicii;
Acest curs ofera o descriere detaliata a sistemului de operare UNIX System V produs de AT&T, atingand si unele aspecte de interes ale altor versiuni. In cuprinsul sau se vor analiza principalele structuri de date si algoritmii utilizati de sistemul de operare.
Acest capitol introductiv trece in revista istoria sistemului UNIX si prezinta structura de ansamblu a sistemului.
Istoric
In 1965 Bell Telephone Laboratories, General Electric Company si Proiectul MAC al Institutului de Tehnologie din Massachusetts au conlucrat in scopul dezvoltarii unui nou sistem de operare, Multics, care urma sa asigure facilitati multiutilizator, puteri sporite de calcul si de stocare a datelor, si posibilitatea partajarii datelor in cazul in care se dorea acest lucru. O prima versiune a Multics-ului a rulat pe un GE 645, insa ea nu s-a ridicat la nivelul asteptarilor. Bell Laboratories se retrage din cadrul proiectului fara ca membrii centrului sau de cercetari in domeniul calculatoarelor sa beneficieze de un 'serviciu de calcul interactiv corespunzator'. In incercarea de a-si dezvolta propriul mediu de programare, Ken Thompson, Dennis Ritchie si altii schiteaza un proiect de sistem de fisiere ce va evolua spre prima versiune de sistem de fisiere UNIX.
Thomson a scris programe care simulau comportamentul sistemului de fisiere propus si al programelor intr-un mediu cu paginare la cerere, realizand chiar un nucleu simplu pentru calculatorul GE 645. In acelasi timp, a realizat in Fortran pentru un sistem GECOS jocul ' Calatorie in spatiu', dar programul nu a avut succes pentru ca 'nava cosmica' era greu de controlat si programul era costisitor. Mai tarziu, a gasit un calculator PDP 7 care asigura o afisare grafica corespunzatoare si o putere de executie convenabila. Programarea jocului pentru PDP 7 i-a permis lui Thompson sa cunoasca bine masina, insa mediul sau pentru dezvoltarea programului a necesitat asamblarea incrucisata a programului pe o masina GECOS si aducerea cartelelor de intrare la PDP 7. Pentru a crea un mediu de dezvoltare mai bun, Thompson si Ritchie au implementat proiectul lor de sistem pe PDP 7, care includea o versiune initiala a sistemului de fisiere UNIX, subsistemul de procese si un mic set de programe utilitare. Noul sistem nu mai avea nevoie de sistemul GECOS ca mediu de dezvoltare, putandu-se sustine singur. Brian Kernigham a numit acest nou sistem de operare - UNIX (un joc de cuvinte al numelui Multics).
Desi aceasta prima versiune de sistem UNIX confirma mare parte din asteptari, nu se putea emite inca o parere asupra potentialului sau pana ce nu era utilizata intr-un proiect real. Astfel, ca urmare a faptului ca asigura un procesor de texte utilizat de departamentul de patentari de la Bell Laboratories, UNIX-ul este mutat in 1971 pe un PDP 11. Sistemul era caracterizat de dimensiunea sa redusa:
16 Ko sistemul de operare;
8 Ko programele utilizator;
un disc de 512 Ko;
limita unui fisier de 64Ko.
Dupa succesul sau de inceput, Thompson a hotarat sa implementeze un compilator de Fortran pentru noul sistem, dar in locul lui vine cu limbajul B influentat de BCPL. B era un limbaj interpretativ, cu dezavantajele caracteristice acestui tip de limbaj, asa incat Ritchie il dezvolta si-l denumeste C. C permite generarea de cod masina, declararea de tipuri de date si definirea de structuri de date. In 1973 sistemul de operare a fost rescris in C, un pas fara precedent la acel moment, dar care urma sa aiba un impact urias in acceptarea sa de catre utilizatori. Numarul de instalari la Bell Laboratories creste la 25, iar pentru a furniza suportul intern, se formeaza Grupul Sistemelor UNIX.
La acel moment AT&T nu putea comercializa echipamente de calcul datorita 'decretului de incuviintare' semnat in 1956 cu guvernul, insa a furnizat sistemul de operare universitatilor care l-au solicitat in scopuri didactice. Desi AT&T s-a conformat termenilor 'decretului de incuviintare', care in cazul de fata interzicea reclama, vanzarile si sustinerea sistemului, popularitatea sa a crescut regulat. In 1974 Thompson si Ritchie au publicat o descriere a sistemului UNIX in 'Comunicarile ACM', descriere ce se va constitui intr-un punct favorabil pentru acceptarea sistemului.
In 1977 numarul utilizatorilor de UNIX crestea la aproape 500, din care 125 erau in universitati. Asigurand un mediu propice pentru dezvoltarea de programe, operatii de tranzactii in retea si servicii in timp real (prin MERT), sistemele UNIX devin populare in cadrul companiilor telefonice. Licentele UNIX sunt furnizate institutiilor comerciale precum si universitatilor. In acelasi an, Interactive System Corporation devine primul VAR (Value Added Reseler) al sistemului UNIX, sporind utilizarea sa in mediile de automatizare a serviciilor. Anul 1977 marcheaza de asemenea anul in care sistemul UNIX a fost instalat in premiera pe o masina non-PDP: Interdata 8/32.
Odata cu cresterea popularitatii microprocesoarelor, alte companii au instalat UNIX-ul pe masini noi, dar simplitatea si claritatea sa au facut ca multi specialisti sa-l imbunatateasca pe cai diferite, rezultand in final mai multe variante ale sistemului de baza. In perioada 1977-1982 Bell Laboratories a combinat mai multe variante AT&T intr-un singur sistem, cunoscut sub numele comercial de UNIX System III. Ulterior, Bell Laboratories i-a adaugat acestuia alte cateva facilitati, rezultand un nou produs, numit UNIX System V. In ianuarie 1983, AT&T si-a anuntat oficial sprijinul pentru System V. Totusi, specialistii de la Universitatea Berkeley din California au dezvoltat o alta varianta a sistemului UNIX pentru calculatoare VAX (cea mai recenta versiune numita BSD 4.3), ce asigura o serie de facilitati noi si interesante. Aceasta carte va descrie in principal UNIX System V, iar ocazional, va aminti si despre trasaturile sistemului BSD.
Pana la inceputul anului 1984 existau aproape 100000 de sisteme UNIX instalate in lume, care rulau pe masini cu diferite puteri de calcul, de la microprocesoare la mainframe-uri. Nici un alt sistem de operare nu realizase o asemenea performanta.
Motivele care au determinat popularitatea si succesul sistemului UNIX sunt:
Sistemul este scris intr-un limbaj de nivel inalt, fapt care-l face usor de citit, inteles, schimbat, sau mutat pe alte masini. Ritchie estima ca primul sistem in C era cu 20-40% mai mare si mai lent pentru ca nu era scris in limbaj de asamblare, insa avantajele utilizarii limbajului de nivel inalt depasesc cu mult dezavantajele.
Are o interfata utilizator simpla care are posibilitatea de a furniza serviciile pe care utilizatorii le doresc.
Furnizeaza primitive care permit realizarea unor programe complexe din programe mai simple.
Utilizeaza un sistem de fisiere ierarhizat care permite intretinerea usoara si implementarea eficienta.
Utilizeaza un format consecvent pentru fisiere si fluxul de octeti, fapt care usureaza scrierea programelor.
Furnizeaza o interfata unitara pentru dispozitivele periferice.
Este un sistem multiutilizator, multitasking (fiecare utilizator poate executa simultan mai multe procese).
Arhitectura masinii este 'ascunsa' utilizatorului ceea ce duce la usurarea scrierii programelor care ruleaza pe diferite arhitecturi hardware.
Simplitatea si consecventa subliniaza valoarea UNIX-ului si justifica multe din calitatile citate anterior.
Desi sistemul de operare si multe din programele de comanda sunt scrise in C, sistemul UNIX suporta si alte limbaje ca: Fortran, Basic, Pascal, Ada, Cobol, Lisp, Prolog. Sistemul de operare UNIX poate suporta orice limbaj care are un compilator sau interpretor si o interfata sistem care pune in corespondenta cererile utilizator de servicii sistem de operare cu un set standard de cereri folosite in sistemele UNIX.
1.2 Structura sistemului
Figura 1.1. descrie arhitectura sistemului UNIX. Hardware-ul din centrul diagramei furnizeaza sistemului serviciile de baza care vor fi descrise in paragraful 1.5.
Figura 1.1. Arhitectura sistemului UNIX
Sistemul de operare interactioneaza direct cu hardware-ul, si furnizeaza servicii de baza programelor pe care le izoleaza de nesincronizarile hardware. Sistemul poate fi privit ca un set de niveluri in care S.O. (sistemul de operare) numit nucleul sistem, sau numai nucleu, este izolat fata de programele utilizator. Deoarece programele sunt independente de nivelul hardware, ele sunt usor de mutat intre sisteme UNIX care ruleaza pe diferite masini daca nu fac presupuneri legate de nivelul hardware. Spre exemplu, programele care presupun o anumita lungime a cuvantului masina sunt mai dificil de mutat pe alte masini decat programele care nu presupun acest lucru.
Programe precum Shell-ul si editoarele (ed si vi), prezente pe nivele urmatoare, interactioneaza cu nucleul prin invocarea unui set bine definit de apeluri sistem. Apelurile sistem cer nucleului sa faca diferite operatii pentru programul apelator si realizeaza schimbul de date intre nucleu si program. Cateva programe prezentate in figura apartin configuratiei standard a sistemului si sunt cunoscute drept comenzi. Pe acest nivel se pot afla si programe utilizator (de exemplu cel cu numele a.out, numele standard pentru fisierele executabile produse de compilatorul C). Pe baza programelor acestui nivel se pot construi alte programe de aplicatii care apartin nivelului exterior din figura. Spre exemplu, compilatorul C standard cc este pe nivelul exterior al figurii: el apeleaza un preprocesor C, un compilator in doi pasi, un asamblor, un editor de legaturi, toate acestea fiind programe separate de nivel inferior. Desi figura prezinta o ierarhie pe doua nivele a aplicatiilor, utilizatorul poate extinde ierarhia pe oricate nivele este necesar. Intr-adevar, stilul programarii sub UNIX incurajeaza combinarea programelor existente pentru realizarea unui task.
Multe subsisteme si programe de aplicatii de nivel inalt precum Shell-ul, editoarele, sistemul de control al codului sursa (SCCS), pachetele de programe pentru procesarea documentelor, au devenit treptat sinonime cu 'sistemul UNIX'. Toate acestea folosesc serviciile de nivel inferior care in cele din urma sunt oferite de nucleu prin setul de apeluri sistem. In System V exista aproape 64 apeluri sistem, din care sunt utilizate frecvent mai putin de 32. Acestea au optiuni simple care le fac usor de utilizat, insa asigura utilizatorului multe facilitati. Setul de apeluri sistem si algoritmii care le implementeaza formeaza corpul nucleului, iar studiul asupra SO UNIX din acest curs se reduce la un studiu detaliat si o analiza a apelurilor sistem si a modului cum interactioneaza intre ele. Pe scurt, nucleul defineste si furnizeaza serviciile care stau la baza tuturor programelor de aplicatii in sistemul UNIX. Pe parcursul lucrarii se vor utiliza in mod frecvent termenii 'sistem UNIX', 'nucleu' sau 'sistem' pentru a referi nucleul S.O. UNIX, iar acest lucru va reiesi clar din context.
1.3 Perspectiva utilizator
Aceasta sectiune trece in revista cele mai importante elementele ale sistemului UNIX cum ar fi: sistemul de fisiere, mediul de procesare, si primitivele pentru constructia blocurilor (ex: pipes). Capitolele urmatoare vor trata in detaliu aceste elemente.
1.3.1 Sistemul de fisiere
Sistemul de fisiere UNIX este caracterizat de :
o structura ierarhizata;
tratare consecventa a fisierelor de date;
usurinta de a crea si sterge fisiere;
marirea dinamica a fisierelor;
protectia fisierelor de date;
tratarea dispozitivelor periferice (cum ar fi terminalele sau imprimantele) ca fisiere.
Figura 1.2. Arborele sistemului de fisiere
Sistemul de fisiere este organizat ca un arbore cu un singur nod radacina, numit root (notat '/'). Nodurile neterminale ale sistemului de fisiere sunt directoare de fisiere, iar fisierele din nodurile terminale (frunze) ale arborelui sunt fie directoare, fie fisiere obisnuite, fie fisiere speciale dispozitiv. Numele fisierului este dat printr-un nume de cale care descrie modul in care poate fi localizat fisierul in ierarhia sistemului de fisiere. Un nume de cale este o secventa de nume de componente separate prin slash ('/'); o componenta este o secventa de caractere care desemneaza un nume de fisier care este unic continut in componenta (directorul) anterioara. Un nume complet de cale incepe cu caracterul slash ('/'), si specifica un fisier ce poate fi gasit plecand din radacina sistemului si traversand arborele prin ramurile care conduc la fisierul cautat. Astfel caile '/etc/passwd', '/bin/who' si '/usr/src/cmd/who.c' definesc fisiere din arborele prezentat in figura 1.2, pe cand '/bin/passwd' si'/usr/src/date.c' nu. O cale poate sa nu inceapa din radacina, putand fi definita relativ la directorul curent al unui proces in executie prin omiterea slash-ului initial din numele caii. Astfel, incepand din directorul '/dev', calea 'tty01' descrie fisierul a carui cale completa ar fi: '/dev/tty01'.
Deoarece nu cunosc formatul intern in care nucleul memoreaza datele in fisiere, programele in sistemul UNIX trateaza datele ca pe un sir neformatat de octeti. Programele pot interpreta sirurile de octeti, dar interpretarea nu are legatura cu modul in care S.O. stocheaza datele. Astfel, sintaxa de acces la datele unui fisier este definita de S.O. si este identica pentru toate programele, insa semantica datelor este impusa de program
Spre exemplu, programul de formatare a textelor troff se asteapta sa gaseasca caracterul 'linie-noua' la sfirsitul fiecarei linii de text, iar programul sistem de contabilitate acctcom se asteapta sa gaseasca inregistrari de lungime fixa. Ambele programe folosesc aceleasi servicii sistem de acces la datele fisierului care este vazut ca un sir de octeti dar intern, acestea analizeaza sirurile in formatul corespunzator. Daca un program descopera ca formatul este incorect, el este raspunzator de actiunile ulterioare.
Directoarele sunt privite ca fisiere obisnuite; sistemul trateaza datele din director ca siruri de octeti, dar datele contin numele fisierelor din director intr-un format specificat astfel incat S.O. si programele precum ls (pentru listarea numelui si atributelor fisierului) sa poata gasi fisierele in director.
Permisiunea de acces la fisiere este controlata prin permisiunile de acces asociate fiecarui fisier. Permisiunile de acces pot fi stabilite independent pentru controlul permisiunii de citire, scriere si executie pentru trei clase de utilizatori: proprietarul fisierului, grupul acestuia si orice alt utilizator neprivilegiat. Utilizatorii pot crea fisiere daca au permisiuni corespunzatoare pentru accesul la director. Fisierele nou create sunt noduri frunze in structura de directoare a sistemului de fisiere.
Din punct de vedere utilizator, dispozitivele sunt tratate de catre S.O.. UNIX ca fisiere. Dispozitivele, descrise prin fisiere speciale, ocupa noduri in structura de directoare a sistemului. Programele acceseaza dispozitivele cu aceeasi sintaxa utilizata pentru accesul fisierelor obtinute; semantica de scriere si citire a dispozitivelor este in mare masura aceeasi ca la citirea si scrierea fisierelor obisnuite. Dispozitivele sunt protejate in acelasi mod ca si fisierele obisnuite (prin setarea permisiunilor de acces). Deoarece numele dispozitivelor sunt vazute ca nume de fisiere obisnuite, si ambele tipuri desi sunt supuse acelorasi tipuri de operatii,
. Spre exemplu, consideram programul in C din figura1.3 care face o copie noua a unui fisier existent. Presupunem ca numele versiunii executabile a programului este copy. Un utilizator apeleaza programul tastand:
copy oldfile newfile
unde oldfile este numele fisierului existent, iar newfile este numele noului fisier. Sistemul apeleaza main inlocuind argc cu numarul de parametri ai listei argv, si initializind fiecare membru al sirului argv cu un pointer spre un parametru furnizat de utilizator. In exemplul anterior, argc este 3, argvs0t pointeaza catre sirul de caractere 'copy' (prin conventie, numele programului este ales parametrul 0), argvs1t pointeaza spre sirul de caractere oldfile, iar argvs2t pointeaza catre sirul de caractere newfile. Programul verifica daca a fost apelat cu numarul corect de parametri. Daca da, atunci lanseaza apelul sistem open pentru fisierul oldfile, iar apoi apelul sistem creat pentru a crea newfile. Modurile de acces pentru fisierul nou creat vor fi 0666(octal), permitindu-se astfel accesul tuturor utilizatorilor la fisier pentru scriere si citire. Toate apelurile sistem returneaza -1 in caz de esec. Daca apelurile open si creat nu se incheie cu succes, programul afiseaza un mesaj si invoca apelul sistem exit, cu returnarea valorii 1, pentru a indica faptul ca ceva a fost gresit.
Apelurile sistem open si creat returneaza un intreg numit descriptor de fisier, pe care programul il foloseste pentru referintele ulterioare la fisier. Apoi, programul apeleaza subrutina copy care ciclic, invoca apelul sistem read pentru a citi din fisierul existent un numar de caractere egal cu dimensiunea bufferului, si apelul sistem write pentru a scrie datele in noul fisier. Apelul sistem read returneaza numarul de octeti cititi, iar 0 cand s-a ajuns la sfirsitul fisierului. Programul termina ciclul cand intilneste sfirsitul fisierului, sau cand exista vreo eroare in apelul sistem read (nu se face verificarea pentru erorile de scriere). Revenirea din copy si terminarea cu valoarea de retur 0, indica faptul ca programul s-a incheiat cu succes.
Programul copiaza orice fisiere furnizate ca argumente, dupa ce se asigura in prealabil ca are permisiunea de deschidere a fisierului existent si cea de creare a noului fisier. Fisierul poate fi unul text, cum ar fi codul sursa al unui program, sau poate contine caractere netiparibile. Astfel, cele doua apeluri:
copy copy.c newcopy.c
copy copy newcopy
sunt corecte. Vechiul fisier poate fi si un director. De exemplu:
copy . dircontents
copiaza continutul directorului curent, dat de numele '.' intr-un fisier obisnuit dircontents; datele din noul fisier sunt identice, octet cu octet, cu continutul directorului, dar fisierul este unul obisnuit (pentru crearea unui director se utilizeaza apelul sistem mknod). De asemenea, vechiul fisier poate fi unul special.
include <fcntl.h>
char buffer[2048];
int version=1; /* explicatii in Cap 2*/
main(argc, argv)
int argc;
char *argvs[ ]t;
/*deschide fisierul sursa*/
fdold = open(argvs[1],O_RDONLY)
if (fdold == -1)
/*creare fisier destinatie cu permisiuni rw pentru toti utilizatorii*/
fdnew = creat (argvs2t,0666);
if (fdnew == -1)
copy(fdold, fdnew);
exit(0);
}
copy(old,new)
int old, new;
Figura 1.3. Program de copiere a unui fisier
De exemplu:
copy /dev/tty terminalread
citeste caracterele tiparite la terminal (fisierul /dev/tty este asociat terminalului utilizatorului) si le copiaza in fisierul terminalread, pana la tastarea caracterului CTRL- D.
1.3.2 Mediul de procesare
Un program este un fisier executabil, iar un proces este o instanta a programului in executie. Sub UNIX pot fi executate simultan mai multe procese (aceasta proprietate fiind numita uneori multiprogramare sau multitasking) fara a exista vreo limitare logica cu privire la numarul acestora. Diferite apeluri sistem permit proceselor sa creeze procese noi, sa termine procese, sa sincronizeze etape ale executiei procesului, si sa controleze reactiile la diferite evenimente. Utilizand apelurile sistem, procesele se executa independent unul de celalalt.
De exemplu, procesul care executa programul din figura 1.4 utilizeaza apelul sistem fork pentru a crea un nou proces.
main(argc,argv)
int argc;
char *argvs[ ]t;
Figura 1.4. Program care creeaza un nou proces pentru copiere
fisiere
Noul proces, numit proces fiu, primeste valoarea 0 la incheierea apelului sistem fork si apeleaza execl pentru a executa programul copy (programul din figura 1.3).Apelul execl suprapune spatiul de adresa al procesului fiu cu fisierul 'copy' (care se presupune a fi in directorul curent) si ruleaza programul cu parametrii dati de utilizator. In acelasi timp, procesul care a invocat fork (tatal) primeste o valoare de retur nenula, apeleaza wait, suspendandu-si executia pana cand programul copy se termina, apoi afiseaza mesajul 'copiere terminata ' si se termina. Spre exemplu, daca numele programului executabil este run si un utilizator invoca programul prin:
run oldfile newfile
Procesul copiaza oldfile in newfile si tipareste mesajul. Desi acest program aduce putine modificari programului copy, el foloseste patru apeluri sistem importante pentru controlul proceselor: fork, exec, wait si exit.
Un program de nivel utilizator care este executat in mod obisnuit dupa intrarea in sistem este shell-ul, programul interpretor de comenzi. Shell-ul interpreteaza primul cuvant din linia de comanda ca nume de comanda. In cazul multor comenzi, shell-ul lanseaza prin fork un proces fiu care la randul sau executa comanda asociata numelui, tratand restul cuvintelor din linia de comanda ca parametrii ai comenzii.
Shell-ul permite trei tipuri de comenzi. In primul rand, o comanda poate fi un fisier executabil care contine codul obiect produs prin compilarea codului sursa (de exemplu al unui program C). In al doilea rand, o comanda poate fi un fisier executabil care contine o secventa de linii de comanda shell. In al treilea rand, o comanda poate fi o comanda shell interna. Comenzile interne fac din interpretorul de comenzi shell si un limbaj de programare care include : comenzi de ciclare (for-in-do-done si while-do-done), comenzi de executie conditionata (if-then-else-fi), o instructiune "case", o comanda de schimbare a directorului curent al procesului (cd) si altele. Sintaxa shell-ului permite 'patern matching' (potrivire de sablon) si procesarea parametrilor. Utilizatorii executa comenzile fara a cunoaste tipul lor.
Cautarea comenzilor se face intr-o secventa de directoare data, ce poate fi schimbata la cererea utilizatorului, invocand shell-ul. In mod obisnuit, shell-ul executa sincron o comanda, asteptind terminarea executiei sale inainte de a citi urmatoarea linie de comanda. Totusi, permite si executii asincrone: citeste urmatoarea linie de comanda si o executa fara a astepta incheierea executiei comenzii anterioare. Comenzile executate asincron se spune ca sunt executate in background.
Spre exemplu, comanda:
who
determina sistemul sa execute programul memorat in fisierul /bin/who care tipareste o lista a persoanelor aflate in sistem in acel moment. Shell-ul asteapta terminarea executiei comenzii who (apelata ca mai sus), dupa care permite utilizatorului introducerea altei comenzi.
Tastand:
who&
sistemul executa programul who in background iar shell-ul este gata sa accepte imediat o alta comanda.
Orice proces executat in sistemul UNIX are un mediu de executie care include directorul curent. Directorul curent al procesului este directorul de inceput utilizat pentru toate numele de cai care nu incep cu caracterul '/'.
Pentru a schimba directorul curent utilizatorul poate executa comanda shell cd. Linia de comanda
cd /usr/src/uts
schimba directorul curent al shell-ului cu directorul "usr/src/uts" .
Linia de comanda:
cd .. /..
schimba directorul curent al shell-ului cu cel care este cu doua noduri mai apropiat de nodul radacina: componenta '..' se refera la directorul 'parinte' al directorului curent.
Deoarece shell-ul este un program de nivel utilizator si nu o parte a nucleului, el este usor de modificat si structurat ca un mediu particular. De exemplu, utilizatorii pot folosi C shell pentru a furniza un mecanism care sa evite retastarea comenzilor utilizate recent, in locul Bourne shell-ului furnizat ca parte a System V. Sistemul poate executa mai multe procese shell simultan.
Utilizatorii au posibilitatea de a executa mai multe procese simultan, iar un proces poate crea alte procese in mod dinamic, si sincroniza executia lor daca doreste. Aceste facilitati asigura utilizatorilor un mediu de executie foarte puternic. Desi puterea shell-ului consta in mare parte in facilitatile sale ca limbaj de programare si in posibilitatea de 'patern matching' a argumentelor, acest paragraf se concentreaza asupra mediului de procesare furnizat de sistem prin shell.
1.3.3 Primitive pentru constructia blocurilor
Asa cum s-a prezentat anterior, la baza proiectarii sistemului de operare UNIX a stat principiul asigurarii utilizatorilor cu primitive de sistem de operare care sa le permita scrierea de programe mici, modulare, care sa poata fi utilizate ca blocuri de constructie pentru programe mai complexe. O astfel de primitiva disponibila utilizatorilor shell-ului este posibilitatea de a redirecta I/O. In mod conventional, procesele au acces la trei fisiere: citesc din fisierul standard de intrare, scriu in fisierul standard de iesire si scriu mesaje de eroare in fisierul standard de erori.
Toate aceste fisiere sunt asociate terminalului, insa fiecare poate fi redirectat independent. De exemplu, linia de comanda
ls
listeaza toate fisierele din directorul curent la iesirea standard, dar linia de comanda
ls >output
redirecteaza iesirea standard catre fisierul numit output din directorul curent, folosind apelul sistem creat mentionat anterior. Similar, linia de comanda
mail mjb<letter
deschide fisierul letter pentru intrarea standard si trimite continutul sau utilizatorului numit mjb. Procesele pot redirecta intrarea si iesirea simultan astfel
nroff -mm<doc1>doc1.out 2>errors
unde procesorul de texte nroff citeste fisierul de intrare doc1, redirecteaza iesirea standard spre fisierul doc1.out si redirecteaza mesajele de eroare spre fisierul errors (notatia '2>' semnifica redirectarea iesirii fisierului cu descriptorul 2 care este, in mod conventional, fisierul standard de erori). Programele ls, mail si nroff nu cunosc care sunt fisierele lor standard de intrare, iesire sau erori; shell-ul recunoaste simbolurile '<', '>' si '2>' si stabileste intrarea standard, iesirea standard si fisierul standard de erori corespunzatoare, inaintea executiei procesulor.
A doua primitiva pentru constructia blocurilor este pipe, un mecanism care permite unui sir de date sa fie trecut de la procesul care scrie la cel care citeste. Un proces poate redirecta iesirea sa standard spre pipe pentru a fi citita de un alt proces care are redirectata intrarea sa standard spre pipe.
Datele scrise de primul proces in pipe sunt intrari pentru procesul al doilea. Al doilea proces poate de asemenea redirecta iesirea sa, si asa mai departe,functie de nevoile de programare.
Nu este necesar ca procesele sa cunoasca care e tipul fisierului standard de iesire fisier obisnuit, pipe sau dispozitiv. Cand foloseste programe mai mici ca blocuri de constructie a unor programe mai mari, programatorul foloseste primitiva pipe si redirectarea I/O pentru integrarea partilor. Sistemul incurajeaza acest stil de programare, incat programele noi pot lucra cu programe deja existente. Spre exemplu, programul grep cauta un ablon dat intr-un set de fisiere (parametrii lui grep) :
grep main a.c b.c c.c
cauta in cele trei fisiere liniile continind cuvantul 'main' si le tipareste la iesirea standard:
a.c: main(argc,argv)
c.c: /*aici este ciclul principal in program*/
c.c: main()
Programul wc cu optiunea ' - l' numara liniile din fisierul standard de intrare. Linia de comanda
grep main a.c b.c c.c | wc - l
numara liniile din fisierele care contin cuvantul 'main'; iesirea lui grep este redirectata spre comanda wc prin pipe.
Pentru exemplul anterior rezultatul este 3. Frecvent, folosirea lui pipe-urilor elimina necesitatea de a crea fisiere temporare.
1.4 Serviciile sistemului de operare
Figura 1.1 prezinta nivelul nucleu imediat sub nivelul programelor de aplicatii utilizator. Nucleul executa diverse operatii cu primitive pentru procesele utilizator care asigura interfata utilizator descrisa mai sus. Printre serviciile furnizate de nucleu sunt:
Controlul executiei proceselor, permitind crearea, terminarea sau suspendarea lor, precum si comunicarea intre ele.
Planificarea corecta a proceselor pentru executia in U.C.P. Procesele au acces la microprocesor intr-o maniera 'time-shared'(partajare in timp) U.C.P.executa un proces, dupa care nucleul il suspenda cand ii expira cuanta de timp alocata si planifica pentru executie un alt proces. Ulterior, nucleul replanifica procesul suspendat.
Alocarea memoriei principale pentru executia unui proces. In anumite conditii nucleul permite proceselor sa‑si partajeze portiuni ale spatiului lor de adresa, protejand insa spatiul de adresa privat al proceselor de modificari din afara. Daca sistemul epuizeaza memoria libera, nucleul elibereaza memorie prin scrierea temporara a unui proces in memoria secundara numita swap device. Daca nucleul scrie in intregime procesele pe swap device, implementarea de S.O. UNIX se numeste sistem cu swapping; daca nucleul scrie pagini de memorie pe swap device, atunci se va numi sistem cu paginare la cerere.
Alocarea de memorie secundara pentru memorarea eficienta si recuperarea datelor utilizator. Acest serviciu constituie sistemul de fisiere. Nucleul aloca spatiu de memorie secundara pentru fisierele utilizator, recupereaza spatiile neutilizate, structureaza sistemul de fisiere intr-o maniera usor de inteles si protejeaza fisierele la accesele nepermise.
Posibilitatea proceselor de a controla accesul la dispozitivele periferice (terminale video, dispozitive de retea, drivere de disc, etc).
Nucleul furnizeaza in mod transparent aceste servicii. Spre exemplu, recunoaste daca un fisier dat este fisier obisnuit sau dispozitiv, dar ascunde aceasta diferentiere procesului utilizator. In mod similar, formateaza datele dintr-un fisier pentru stocarea interna, dar ascunde formatul intern proceselor utilizator, returnand un sir de octeti neformatat. Nucleul permite shell-ului sa citeasca intrarea de la terminal, sa creeze in mod dinamic procese, sa sincronizeze executia proceselor, sa creeze pipe-uri si sa redirecteze I/O. Utilizatorii pot construi versiuni de shell cu specificatii proprii, fara a afecta alti utilizatori. Aceste programe folosesc aceleasi servicii ale nucleului ca si shell-ul standard.
1.5 Cerinte asupra hardware-ului
Executia proceselor utilizator in sistemele UNIX este impartita pe 2 nivele: utilizator si nucleu. Cand un utilizator executa un apel sistem, modul de executie al procesului se schimba din modul utilizator in modul nucleu: sistemul de operare incearca sa serveasca cererea utilizatorului, returnand un cod de eroare in caz de nereusita. Chiar daca utilizatorul nu face cereri explicite de utilizare a serviciilor sistemului de operare, totusi acesta executa operatiile legate de procesul utilizator tratand intreruperile, planificand procesele, gestionand memoria, s.a.m.d. Multe arhitecturi de masini de calcul suporta mai mult de doua nivele, insa aceste doua moduri, 'utilizator' si 'nucleu', sunt suficiente pentru sistemul UNIX.
Diferentele intre cele doua moduri sunt:
Procesele in mod utilizator pot accesa propriile instructiuni si date, dar nu si instructiunile si datele nucleului (sau cele ale altui proces). Procesele in mod nucleu pot accesa oricand adresele nucleu sau utilizator. Spre exemplu, spatiul de adresa virtuala al unui proces poate fi impartit in adrese care sunt accesibile numai in modul nucleu si adrese accesibile in orice mod.
Unele instructiuni masina sunt privilegiate si dau eroare cand sunt executate in modul utilizator. De exemplu, o masina poate contine o instructiune care manipuleaza registrii de stare ai procesului; procesele executate in modul utilizator nu trebuie sa aiba aceasta posibilitate.
Hardware-ul 'vede ' exteriorul in termenii modului nucleu si utilizator si nu face distinctia intre mai multi utilizatori care executa programe in acelasi mod. Figura 1.5 arata cum nucleul face distinctie intre procese pe orizontala, iar hardware-ul pe verticala.
Figura1.5. Procese multiple si modurile de executie
Desi sistemul executa intr-unul din cele doua moduri, nucleul este executat pentru un utilizator. Nucleul nu este un set separat de procese care ruleaza in paralel cu procesele utilizator, ci este parte a fiecarui proces utilizator. In continuare se vor folosi formularile: 'alocarea resurselor de catre nucleu' sau 'nucleul executa diferite operatii', dar prin ele se intelege ca un proces care se executa in modul nucleu aloca resurse sau executa diferite operatii. De exemplu, shell-ul citeste intrarea de la terminalul utilizatorului printr-un apel sistem; nucleul, executat pentru procesul shell, controleaza operatiile terminalului si returneaza caracterele tiparite catre shell. Shell-ul se executa apoi in modul utilizator, interpreteaza sirul de caractere tiparit de utilizator si executa o serie de actiuni specifice care pot necesita invocarea altor apeluri sistem.
Intreruperi si exceptii
Sistemul UNIX permite dispozitivelor precum perifericele de I/O sau ceasul sistem sa intrerupa U.C.P. in mod asincron.
La primirea intreruperii, nucleul salveaza contextul curent (o imagine a ceea ce procesul executa), determina cauza intreruperii si trateaza intreruperea. Dupa ce nucleul trateaza intreruperea, el reface contextul si continua ca si cum nu s-ar fi intamplat nimic. In mod obisnuit, hardware-ul acorda prioritate dispozitivelor in functie de ordinea in care intreruperile trebuiesc tratate: cand nucleul trateaza o intrerupere, blocheaza intreruperile cu prioritate mai mica si le serveste pe cele cu prioritate mai mare.
Exceptiile se refera la evenimente neasteptate, cauzate de procese, cum ar fi adresarea ilegala a memoriei, executia instructiunilor privilegiate, impartirea la zero, si altele. Spre deosebire de exceptii, intreruperile sunt cauzate de evenimente externe procesului. Exceptiile apar in "mijlocul" executiei unei instructiuni, iar sistemul incearca sa execute din nou instructiunea dupa tratarea exceptiei. Se considera ca intreruperile apar intre executia a doua instructiuni, iar sistemul continua cu instructiunea urmatoare dupa servirea intreruperii. Sistemul UNIX foloseste un mecanism unic de tratare a intreruperilor si a exceptiilor.
Nivele de executie ale procesorului
Uneori, nucleul trebuie ca pe durata secventelor critice sa previna aparitia intreruperilor deoarece acestea ar putea duce la alterarea datelor daca ar fi permise. De exemplu, nucleul trebuie sa nu accepte intreruperea de disc cat timp manipuleaza liste inlantuite, deoarece tratarea intreruperii poate deteriora pointerii (vezi capitolul urmator).
Figura 1.6. Nivele de intreruperi obisnuite
In mod obisnuit, calculatoarele au un set de instructiuni privilegiate care seteaza nivelul de executie al procesorului intr-un cuvant de stare al procesului. Setand nivelul de executie al procesorului la anumite valori, se mascheaza intreruperile pentru acel nivel si pentru cele inferioare, permitindu-se numai intreruperile de nivel superior. Figura 1.6 arata un set simplu de nivele de executie.
Daca nucleul mascheaza intreruperile de disc, sunt impiedicate toate intreruperile, cu exceptia intreruperii de ceas si a intreruperilor datorate unor erori ale masinii. Daca se mascheaza intreruperile software, toate celelalte intreruperi sunt active.
Gestiunea memoriei
Nucleul se gaseste permanent in memoria principala ca parte a procesului aflat in executie la acel moment. Cand se compileaza un program, compilatorul genereaza un set de adrese program care reprezinta adresele variabilelor si structurilor de date, sau adresele instructiunilor sau functiilor. Compilatorul genereaza adresele pentru o masina virtuala ca si cum nici un alt program nu va fi executat simultan pe masina fizica.
Cand programul este rulat pe masina, nucleul aloca spatiu in memoria principala pentru acesta, dar adresele virtuale generate de compilator nu trebuie sa fie neaparat identice cu adresele fizice pe care le vor ocupa in memorie. Nucleul coordoneaza headware-ul masinii pentru a stabili translatarea adreselor virtuale in adrese fizice. Translatarea depinde de posibilitatile hardware-ului masinii, iar partea sistemului UNIX care se ocupa cu acest lucru este de aceea dependenta de masina. De exemplu, unele masini au un hardware special care suporta paginarea la cerere.
Copyright © 2024 - Toate drepturile rezervate