CATEGORII DOCUMENTE |
Perspectiva utilizator - UNIX
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 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 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.
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.
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.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1060
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved