|
Politica de confidentialitate |
|
• domnisoara hus • legume • istoria unui galban • metanol • recapitulare • profitul • caract • comentariu liric • radiolocatia • praslea cel voinic si merele da aur | |
Fisiere UNIX | ||||||
|
||||||
Sistemul de fisiere constituie locul unde se memoreaza pe suport fizic fisierele sistem si cele utilizator. Sistemul de fisiere este caracterizat prin trei aspecte: - structura ierarhica; i5c19cc Structura ierarhica este organizata sub forma unui arbore cu un director radacina (/). Directorul radacina poate contine fisiere, legaturi sau alte directoare, numite subdirectoare. Subdirectoarele sunt noduri in arbore, iar fisierele sunt frunze. Independenta fata de hardware rezulta din faptul ca fisierele sunt privite ca o succesiune de octeti. Flexibilitatea se bazeaza pe posibilitatea de a monta sau demonta, la orice nivel in ierarhia de fisiere, noi structuri arborescente de directoare si fisiere. Nivelul de sub radacina este tipic, fiind comun tuturor sistemelor de operare compatibile UNIX. In orice sistem Unix, subdirectorul radacina se gasesc urmatoarele subdirectoare: bin, dev, etc, lib, tmp, usr (care la rindul lui contine subdirectoarele: bin, include, lib, user, man) s.a.m.d. Structura arborescenta a sistemului de fisiere ofera utilizatorului posibilitatea de a crea si gestiona un numar mare de fisiere. Principalele particularitati ale sistemului de fisiere sunt: Numele unui fisier poate fi de orice lungime (versiunile vechi limitau numele unui fisier la maxim 14 caractere) si poate contine orice caractere,
mai putin caracterele slash (/) si caracterul NULL (marcajul de sfirsit de sir). In Unix se deosebesc patru tipuri de fisiere: ordinare, speciale, fisierele pipe si directoare. Din punct de vedere al sistemului de operare un fisier este un sir de octeti de lungime nedefinita terminat cu caracterul special de sfirsit de fisier (EOF). Citirea sau scrierea incepe de la o locatie de octet specificata prin pointerul de fisier (sau marker), care poate fi pozitionat oriunde in fisier. Un fisier ordinar este creat de un proces. El poate contine o sursa Fisierele speciale sunt fisiere atasate dispozitivelor de I/E. In directorul /dev se gasesc toate referintele la dispozitivele de I/E: discuri, benzi magnetice, terminale, imprimante, mouse etc. Acestea sunt considerate fisiere speciale. De exemplu, pentru fiecare partitie a unui hard disc se gaseste cite un fisier special. Un fisier special are un i-node, care insa nu refera un bloc de date pe disc. In schimb, acest i-node contine un numar de dispozitiv, care este folosit ca index intr-o tabela de proceduri, din nucleu, pentru dispozitive periferice. Pentru identificarea fiecarui dispozitiv se folosesc doua numere: minor (identifica numarul dispozitivului de tipul dat) si major (identifica tipul dispozitivului). Exista doua tipuri de dispozitive pentru fisiere speciale: in mod bloc si in mod caracter. Cele in mod bloc contin un vector de blocuri de dimensiune fixa, iar tampoanele nucleu sunt folosite ca si cache pentru cresterea vitezei operatiilor de I/E. Cele in mod caracter realizeaza operatiile de I/E la nivel de caracter sau la nivel de pista. Acelasi dispozitiv fizic poate detine fisiere speciale atit in mod caracter cit si in mod bloc. Fisierele ordinare si directoarele sunt accesate de sistemul de fisiere printr-un fisier special in mod bloc, pentru a beneficia de avantajele tampoanelor cache. Pe de alta parte, unele aplicatii (baze de date) necesita un acces direct. Multe sisteme Unix folosesc un fisier special in mod caracter care transfera datele direct intre spatiul de adrese al procesului si disc (folosind DMA). Din punct de vedere utilizator nu exista nici o diferenta intre lucrul cu fisiere ordinare si cele speciale. De exemplu: $ cp prg.c /usr/acct/k/prg1.c #copiere simpla Fisierele pipe si fisierele FIFO vor fi tratate pe larg intr-un laborator urmator. Un fisier face legatura intre numele fisierelor si i-node. El nu contine efectiv fisierele care ii apartin ci doar referintele la acestea, sub forma unei succesiuni neordonate de intrari. Orice intrare director este formata din numele fisierului si un numar de identificare. Acesta din urma refera un nod de identificare, i-node, in care sunt pastrate informatiile referitoare la fisierul in cauza. Fiecare fisier are un singur i-node care contine: 1. Proprietarul fisierului si drepturile de acces ale celorlalti utilizatori. Directorul este pastrat ca un fisier ordinar, dar este marcat ca director in i-node. Un fisier director poate fi citit ca orice fisier, dar nu poate fi scris in mod direct, ci numai prin intermediul anumitor programe. O pereche (nume_fisier, i-node) este numita in Unix legatura. In Unix este posibil ca doua legaturi, din acelasi director sau din directoare diferite, sa refere acelasi i-node. Aceasta inseamna ca un fisier poate fi identificat sub mai multe nume (fara a exista ambiguitate). Daca i-node-ul este 0, intrarea respectiva este vida, adica legatura a fost stearsa. Pentru legarea la orice director a unui fisier dintr-un director se poate folosi comanda ln (link). Sintaxa ei este: ln <nume_cale_veche> <nume_cale_noua> Comanda este identica cu functia de sistem link. Stergerea unei legaturi se poate realiza prin comanda sau apelul de sistem unlink. La stergerea unei
legaturi dintr-un director i-node-ul si blocurile de date asociate nu sunt disponibilizate caci s-ar putea sa mai existe un alt fisier care sa refere acelasi i-node. Din acest motiv i-node-ul contine in structura sa un cimp numit contorul
de legaturi. Stergerea unei legaturi implica decrementarea contorului de legaturi Legarea directoarelor este posibila, dar numai de catre superuser. O alta caracteristica a sistemului Unix este posibilitatea de a monta un intreg arbore de fisiere undeva in structura altui sistem de fisiere. Operatii de I/E Un proces poate accesa un fisier prin descriptorul de fisier. La crearea sau deschiderea unui fisier nucleul intoarce prin functiile de sistem folosite descriptorul atasat fisierului. Redirectarea fisierelor standard. Conectarea programelor prin pipe La deschiderea fiecarei sesiuni utilizator shell-ul deschide in mod automat cele trei trei fisiere: fisierul standard de intrare, fisiereul standard de iesire si fisierul standard de afisare a erorilor si sint atribuite terminalului la care s-a deschis sesiunea respectiva. Daca se executa o comanda, procesul fiu creat de shell mosteneste fisierele deschise,
inclusiv cele standard. comanda a1) determina listarea directorului curent in fisierul fis1 (stergind
continutul anterior al acestuia), in timp ce comanda a2) determina adaugarea
continutului directorului la sfirsitul lui fis1. b) operatorul "<" redirecteaza fisierul standard de intrare. Exemplu
realizeaza trimiterea catre utilizatorul user1 a unui mesaj citit din fisierul
letter si nu de la tastatura. solicita executia comenzii who in mod concurent cu comanda lpr, iesirea lui
$ who > fisier_temporar Intre cele doua solutii exista insa urmatoarele diferente majore: int pa2i, status, child1, child2; pipe(p); if (child = fork()) == 0) A close(1); dup(pa1i); close(pa1i); close(pa0i); exec1("/bin/who", "/bin/who", 0); Pina in acest moment, s-a presupus ca toate comenzile prezentate sint introduse de utilizator de la tastatura si sint apoi direct executate. Astfel,
limbajul de comanda SHELL a fost privit ca un limbaj control al lucrarilor Variabila shell O variabila shell se defineste printr-un nume, care poate avea ca va loare un sir de caractere, atribuit cu semnul egal "=", precum urmeaza variabila = valoare atribuire : $ pozit = /usr/ion utilizare : $ cd $pozit $HOME se refera la directorul alocat utilizatorului la intrarea in sesiune (argument implicit al comenzii cd); $echo $PATH Valoarea variabilei HOME se poate folosi in comenzi ca de exemplu: $mv raport $HOME/Docum pentru a evita introducerea in intregime a numelui de cale pentru directorul destinatie. Procedura shell O procedura shell este o colectie de comenzi sau instructiuni ale limbajului
de comanda shell ce pot fi preluate dintr-un fisier text sau de la tastatura.
a) $sh fis1 sau b) $chmod fis1 a+x unde fis1 este un fisier text. Procedurile shell pot contine parametri, interpretati pozitional, pentru care sunt substituite valorile reale la momentul executiei. In interiorul unei proceduri, parametrii de la lina de comanda sunt referiti prin simbolurile $1, ... $9 si sunt substituiti pozitional dupa cum urmeaza : Pentru exemplificare se presupune ca se doreste un listing cu toti utilizatorii
conectati la un anumit tip de terminal si nu pentru orice tip posibil, deoa-
rece sirul de caractere 'tty' este in mod permanent inclus in definire. Un filtru este o comanda care are urmatoarea schema de lucru : a) citeste un fisier; b) prelucreaza acel fisier intr-un anumit fel; c) tipareste rezultatul prelucrarii. Comanda 'grep' extrage dintr-un fisier acele linii care contin o configuratie predeterminata de caractere. Procedura va contine o singura linie : who | grep tty si se poate lansa in executie prin : $sh whotty Rezultatul obtinut poate fi de forma: petre tty2 mar 15 11:43 Procedura 'whotty' se poate generaliza, utilizand un parametru pe linia de
comanda, care reprezinta tipul terminalului. Ca de exemplu in procedura who | grep $1 Astfel secventa : $sh whoterm tty va afisa : petre tty2 mar 15 11:43 exact acelasi rezultat ca si 'whotty', intrucat $1 va fi substituit, la executie, prin sirul de caractere "tty". Se poate folosi, deci, aceiasi procedura pentru afisarea numelor utilizatorilor conectati la orice tip de terminal. Fisierul ".profile" . Acest fisier al carui continut este constituit din comenzi sau instructiuni catre shell, permite configurarea mediului de lucru propriu al unui utilizator si este citit si executat de catre shell la fiecare deschidere a unei sesiuni utilizator. De exemplu, daca in fisierul ".profile" exista liniile urmatoare, atunci terminalul cu care se lucreaza este de tip 'vt100', si la fiecare conectare se va starta executia programului 'calendar' : TERM=vt100 export TERM calendar Daca se doreste vizualizarea pe ecran a continutului acestui fisier, se va
putea folosi, de exemplu, comanda : Numele acestui fisier incepe cu "." pentru a nu fi listat decat la apelul comenzii 'ls' cu parametrul '-a', un utilizator neavizat nefiind astfel constient de existenta acestuia. Fisierele '/etc/environment' si '/etc/profile'. Afisarea variabilelor de mediu curente se poate face cu comanda 'env' : $env Exportul variabilei. Mediul unei comenzi este reprezentat de valorile variabilelor shell care sunt cunoscute de acea comanda. Valorile variabilelor de mediu pozitionate de catre shell nu sunt mostenite
in mod explicit de catre procesele lansate de acesta. Pentru ca un proces sa poata folosi o valoare a unei variabile de mediu, atribuirea acesteia trebuie
sa se faca pe linia de comanda (de obicei inaintea numelui comenzii) sau in
interiorul programului. Sa presupunem, de exemplu, ca fisierul de comenzi echo $term In acest caz, secventa de comenzi : $term=vt100 nu va afisa nimic, deoarece variabila 'term' nu este cunoscuta in fisierul
$term=vt100 bubu Aceste atribuiri sunt valabile numai pe durata executiei comenzii. Pentru a face cunoscute valorile variabilelor de mediu asociate unui anumit proces in
afara acestuia (tuturor proceselor lansate in acelasi shell) se foloseste comanda interna 'export'. Astfel, daca se doreste ca valoarea variabilei term=vt100 export term Instructiunea 'export' este apelata in fisierele '/etc/profile' si '.profile' pentru a face cunoscute tuturor programelor anumite variabile de mediu ale shell-ului ce au o importantza deosebita cum ar fi : PATH, HOME, TERM etc. Executie conditionata.Modul de terminare a executiei unei comenzi este memorat de shell intr-o vari abila interna numita 'exit status' (stare de iesire). Valoarea sa poate fi testata de utilizator pentru a determina modul in care s-a incheiat executia ultimei comenzi (zero -succes, diferit de zero -eroare). Shell-ul poate apoi utiliza 'exit status' pentru a decide asupra actiunii urmatoare. Interpretorul prevede trei constructii de baza pentru executia conditionata : constructiile 'if', 'while' si 'until'. Constructia 'if' exista in doua forme : if ... then si if ... then ... else precum este iustrat in urmatarele doua situatii : if lista_de_comenzi then lista_de_comenzi fi si if lista_de_comenzi then lista_de_comenzi else lista_de_comenzi fi In constructia 'if' se verifica intotdeauna doar succesul ultimei comenzi din lista deoarece shell-ul tine evidenta doar a unui singur indicator de tip until lista_de_comenzi do lista_de_comenzi done Sa presupunem ca trebuie scris un program shell care asteapta pina cind este creat un anumit fisier. O metoda ar fi sa se utilizeze structura while: while test! -r procedure; do sleep 1; done O alta metoda foloseste structura until: until test -r procedure; do sleep 1; done Interpretorul de comenzi contine, de asemenea, doua comenzi interne numite true si false, care returneaza respectiv o stare de iesire zero si unu. while true do date; sleep 60; done Shell-ul de tip Bourne are doi operatori conditionali: Cind doua comenzi sint separate printr-un dublu ampersand, a doua comanda se va executa doar daca prima comanda reintoarce starea de iesire zero. Astfel comanda $ test -d /usr/kc&&echo succes! va tipari mesajul succes! daca fisierul /usr/kc este un director (-d). -operatorul bara dubla "||". Daca doua comenzi sint separate prin aceste 2 bare, se va executa a doua comanda daca prima comanda reintoarce o stare de iesire (exit status) nonzero. $ test -d /usr/kc || echo eroare! va tipari mesajul eroare!, daca fisierul nu exista sau daca el exista dar nu este fisier director. Concluzii la limbajul de comanda al Shellului In proiectarea unei aplicatii nu foarte complexe, utilizatorul poate opta pentru limbajul de comanda al shell-ului in locul unui limbaj de nivel inalt Caracteristici ANSI C Toate exemplele descrise in continuare sunt scrise in limbajul C care respecta standardul ANSI C. Prototipul si interfata unei functii Fisierul antet unistd.h contine prototipul multor functii oferite de sistemul Unix. Prototipul unei functii specifica tipul parametrilor de apel si tipul valorii returnate de functie. Exemple de prototip de functii sunt: pid_t getpid( void); ssize_t read( int, void *, size_t); void *malloc( size_t); In primul caz functia getpid nu are argumente si returneaza o valoare de tipul pid_t. In al doilea caz functia read are trei argumente de tipuri diferite: int, un pointer la tipul void si size_t. Valoarea returnata de functie este
de tipul ssize_t. In ultimul caz, functia malloc are un singur argument de tipul size_t si valoarea returnata este un pointer la tipul void. In versiunile anterioare de UNIX nu era definit tipul void motiv pentru care prototipul acestor functii folosea in loc de void tipul int iar in loc
de void * tipul char *. Introducerea tipului void permite eliminarea castului.
int *p; p=malloc( 77 * sizeof( int)); Compilatorul folosit, gcc sau cc, respecta standardul ANSI C. In versiunile anterioare de UNIX nu erau definite tipurile pid_t, ssize_t si size_t folosite in exemplele anterior prezentate. Aceste tipuri de date si in general toate tipurile terminate cu _t sunt definite ca tipuri primitive de sistem in fisierul antet sys/types.h Cele doua fisiere antet unistd.h si sys/types.h au rolul de a preveni programele sa foloseasca tipuri specifice de date. Astfel, fiecare implementare alege acele date care sunt impuse de un anumit sistem. De exemplu, daca se doreste gasirea identificatorului de proces, se aloca o variabila de tip pid_t pentru a memora valoarea returnata de functia getpid. Definitia acestui tip poate sa difere de la o implementare la alt, dar ea se reduce la inlocuirea unui singur fisier (care se include) si aplicatia poate fi recompilata. Timpul in UNIX Exista doua timpuri diferite pastrate de sistemul UNIX. Primul este timpul calendar. Acesta valoare precizeaza numarul de secunde scurse de la La masurarea timpului de executie a unui proces, UNIX-ul pastreaza trei valori: Timpul real consumat este timpul cit procesul se executa. Acesta depinde de incarcarea sistemului, adica de numarul proceselor care se executa in sistem. Timpul CPU consumat in mod utilizator este timpul scurs pentru executia instructiunilor utilizatorului. Timpul CPU consumat in mod nucleu este timpul scurs pentru executia functiilor de sistem aferente procesului (de exemplu, timpul scurs pentru rezolvarea unui apel read de catre nucleu). Pentru a masura acesti timpi se poate executa executa comanda time, care va avea ca argument comanda pentru care se doreste a fi efectuata masuratoarea. De exemplu, pentru a masura timpul scurs intr-o operatie de cautare a secventei "_POSIX_" in toate fisierele dintr-un director se poate folosi: $cd /usr/include Iesirea acestui program depinde de interpretorul folosit. Semnale Semnalul este un mecanism de sincronizare important in sistem prin care un proces este informat asupra aparitiei unui eveniment. Semnalul poate proveni de la nucleu, de la un alt proces, chiar de la acelasi proces si de la utilizator. Un exemplu de semnal provenit de la nucleu este semnalul SIGSEGV
transmis procesului care incearca un acces la memorie in afara propriului spatiu de adrese. Un proces poate trimite la alt proces un semnal de terminare
a. sa ignore semnalul, lucru nerecomandat in cazul semnalelor ce indica erori hardware (de exemplu impartirea cu 0); b. sa execute actiunea implicita atasata semnalului (de exemplu pentru impartirea cu 0 actiunea implicita este terminarea); c. sa execute o rutina (functie) de tratare a semnalului. Nu se poate opta pentru oricare dintre alternative pentru orice semnal. Comunicarea intre procese Comunicarea intre procese (IPC=Inter Proces Comunication) se poate realiza in diverse moduri: semnale, fisiere, pipe, pipe cu nume, semafoare, mesaje, memorie partajata, socket si stream. Tipurile de comunicatie folosite actualmente mai des si permise de diverse versiuni de UNIX sunt ilustrate in tabelul 1. Primele cinci metode sunt folosite de procese aflate pe acelasi host, iar ultimele doua metode sunt folosite de procese aflate si pe host-uri diferite. --------------------------------------------------------------------- | Tipuri de comunicare | V7 | SVR | 2SVR3.2 | SVR4 | 4.3BSD | 4.3+BSD | Semnalele sunt folosite de procese pentru a informa alte procese. Din pacate semnalele nu contin suficienta informatie, deseori necesara in aplicatii.
Prin trasarea procesului, un proces parinte poate controla executia unui proces fiu. Doarece procesul tata poate citi si scrie datele procesului
fiu, cele doua procese pot comunica liber. Trasarea proceselor este folosita
numai in depanatoare, doearece este complicata si nesigura pentru uz general.
Comunicarea printr-un fisier este o metoda simpla prin care procesele pot schimba date. De exemplu, un proces ce executa editorul ed poate scrie intr-un fisier, iar alt proces ce executa utilitarul nroff poate sa-l formateze.
a. daca cele doua procese lucreaza concurent, nu exista sincronizare corecta intre procese (procesul cititor poate conchide din detectarea unui sfirsit de fisier gresit, terminarea comunicarii); b. daca comunicarea este de durata, dimensiunea fisierului creste considerabil. Folosirea unui fisier gol pe post de semafor este o tehnica des folosita in UNIX. Pipe rezolva problema de sincronizare a fisierelor. Cu toate ca are un i-node atasat, nu exista referinta la el. Citirea si scrierea unui pipe este
asemanatoare cu citirea si scrierea unui fisier, dar exista diferente majore.
a. procesele care comunica trebuie sa fie in relatia parinte fiu sau cu stramos comun (inconvenient major cind, spre exemplu, unul dintre procese este gestionarul unei baze de date, iar celalalt o aplicatie care gestioneaza baza); b. versiunile mai vechi nu ofera citire si scriere atomica pentru pipe cu mai multe procese ce scriu si citesc (acelasi proces gestionar al bazei de date si mai multi clienti care lanseaza cereri); c. operatii lente, cu toate ca nu se fac operatii de I/E, copierea user-kernel si invers pot fi critice pentru unele aplicatii. Pipe cu nume, numite si FIFO au aparut odata cu versiunea III pentru a elimina primele doua neajunsuri. Un fisier FIFO se comporta ca un fisier pipe si orice proces, daca are drepturi poate sa-l acceseze. Atomicitatea operatiilor este asigurata. Singurul dezavantaj ramine viteza, mult prea lenta pentru unele aplicatii. Semaforul este un fanion care previne doua sau mai multe procese sa acceseze simultan aceasi resursa. Mesajul este un pachet mic de date, ce poate fi trimis intr-o coada de masaje. Mesajele pot fi de diferite tipuri. Orice proces, daca are drepturile necesare, poate primi un mesaj din coada. Mesajul poate fi ales: fie primul, fie primul de un anumit tip, fie primul dintr-un anumit grup de tipuri. Memoria partajata este mijlocul de comunicatie cel mai rapid. Principiul este simplu: acelasi spatiu de memorie este mapat in spatiul de adrese a doua sau mai multe procese. Cit de repede datele sunt scrise in memoria partajata, atit de repede pot fi disponibile procesului cititor. Un semafor sau mesaj este utilizat pentru a sincroniza procesul care scrie in raport cu cel care citeste. Gestionarea erorilor ÚAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¿ extern int errno; Valoarea variabilei errno nu este stearsa de apelul unei functii fara eroare. Daca insa valoarea variabilei nu este testata in cazul unei erori, apelul urmator al unei functii poate suprascrie valoarea variabilei. Valoarea
Standardul C defineste doua functii utile pentru afisarea mesajelor de eroare. Prima este strerror cu interfata: #include <string.h> char *strerror( int nrerr); care intoarce pointerul la mesajul de eroare. Aceasta functie realizeaza corespondenta intre nrerr (este de regula valoarea variabilei errno) si mesajul de eroare aferent erorii. A doua functie
este perror si are interfata: Functia afiseaza la iesirea standard de erori mesajul msg urmat de caracterul ':', un caracter vid si mesajul aferent valorii din variabila errno. Ex 1: int main(int argc,char *argvai) errno=ENOENT; perror( argva0i); if ( read( fd, buf, no) == -1) err_sys("Eroare read"); exit(0); p1 < input | p2 | p3 > output deoarece se poate preciza exact programul care a generat mesajul de eroare. $a.out Pentru a nu apela aceste functii direct si din ratiuni de spatiu(pentru a nu extinde fiecare exemplu cu liniile de tratare a erorilor) toate exemplele
vor include la compilare fisierul err.c sau direct fisierul obiect err.o Procesul este un program in executie. Ca urmere, procesul este dinamic, pe cind programul este static. Pentru un program dat (fisier executabil) pot exista la un moment dat unul sau mai multe procese asociate, numite instante. La executia unei comenzi de catre shell aceasta citeste linia de comanda si desparte comanda de argumentele sale. Se apeleaza functia sustem fork in urma careia rezulta cele doua procese: parintele si fiul. Procesul parinte printr-un apel al functiei de sistem wait cedeaza procesorul procesului fiu. Acesta la randul sau printr-un apel al functiei de sistem exec executa un nou program, care este chiar comanda data. Nucleul incarca in zona de memorie a shell-ului noul program si procesul este continuat cu acest program, caruia ii sunt transmise argumentele. In cadrul procesului nu se schimba decit programul, restul ramane nemodificat. La incheierea executiei programului se apeleaza functia sistem exit, care cauzeaza terminarea procesului fiu si iesirea din starea de asteptare a procesului parinte. Executia unui program utilizator se poate face in doua moduri:in modul utilizator si in modul nucleu (sau sistem) asociate modului de functionare ale procesului. - segmentul de date - segmentul de stiva Un fisier executabil contine antetul, segmentul text si date (numai cele initializate). Deoarece un proces se poate executa in modul utilizator
si nucleu, i se mai asociaza si o stiva nucleu, care va contine informatii necesare pentru functiile sistem. Un proces trece din modul utilizator in cel
nucleu cand se apeleaza o functie de sistem sau cand este generata o intrerupere. Functia malloc #include <stdlib.h> void *malloc( dimensiune); Exemplu de utilizare: void *ptr; if ((ptr = malloc (10000)) == NULL)A perror( "malloc"); exit(1); (in octeti) si o initializeaza cu caracterul NULL. Interfata sa este: #include <stdlib.h> void *calloc( size_t nr_elem, size_t dim_element); Intoarce un pointer diferit de 0 in caz de succes, NULL in caz de eroare. Exemplu de utilizre: struct A int s1; long s2; char s3a10i; Functia realloc #include <stdlib.h> void *realloc( void *ptr, size_t new_dim); Intoarce un pointer diferit de zero in caz de succes, NULL in caz de eroare. Exemplu de utilizare: void *ptr; Functia free elibereaza o zona de memorie alocata prin malloc, calloc sau realloc. include ,stdlib.h> free( void *ptr) Revenirea din functie se considera ca o tratare corecta. Dar daca ptr era eronat, rezultatul este imprevizibil. Exemplu de utilizare: void *ptr; Se mentioneaza faptul ca la segmentul de date poate fi atasata si o zona de memorie comuna, lucru prezentat in cadrul comunicarii intre procese. main( int argc, char *argvai, char *envpai) Numarul elementelor tabloului de adrese referit de argv este argc. /* afisarea argumentelor de apel */ for ( k=0; k<argc; ++k) A printf( parametrul nr d este: s\nn", k+1, argvaki; NUME = valoare Unele dintre cele mai uzuale valori care se gasesc in mediul transmis unui program sunt: HOME - numele de cale al directorului de referinta; Observatii: a. Mediul program curent poate fi afisat prin comanda env. b. In programe, variabilele mediului pot fi recuperate nu numai prin argumentul envp mai sus prezentat, ci si prin variabila externa environ, care este un pointer la un tablou de pointeri catre sirurile de caractere care semnifica variabilele mediului. Exemplu: extern char **environ; main() Recuperarea variabilelor de mediu prin envp si environ sunt echivalente. c. Recuperarea valorii unei variabile de mediu se poate face cu functia getenv care are interfata: #include <stdlib.h> char *getenv (const char *nume); Intoarce un pointer la valoarea variabilei asociate cu nume, NULL in cazul absentei variabilei. Exemplu: Identificatori. Identificatorul utilizatorului Identificatorul utilizatorului, pe scurt ID utilizator, din cimpul al treilea al unei intrari din fisierul /etc/passwd este un numar intreg pozitiv prin care sistemul identifica utilizatorul. Acest numar este atribuit utilizatorului de catre administratorul de sistem, la introducerea unui nou utilizator in sistem. Acest ID este, de regula, unic si nu poate fi modificat. Identificatorul grupului Asemeni ID-ului utilizatorului, ID-ul grupului este atribuit de catre administratorul de sistem, la introducerea unui nou utilizator in sistem. Grupul serveste la reunirea acelor utilizatori care folosesc partajat anumite resurse ls -l afiseaza numele proprietarului unui fisier folosind fisierul de parole. ID de grup al utilizatorului care a deschis sesiunea de lucru va fi fixat ca ID de grup pentru procesul shell. Acesta va fi mostenit de toate procesele descendente din shell. ID-ul grupului este numit si ID-ul grupului real. Identificatori suplimentari de grup Incepind cu versiunea 4.2BSD un utilizator poate adera la mai multe grupuri (maxim 16). ID-ul grupurilor suplimentare se obtin din fisierul Pentru procese avem : a. Identificatorul de proces Este un numar intreg mai mare sau egal cu 0. El este in strinsa corelatie cu intrarea in tabela proceselor. Procesul cu identificatorul 0 este procesul swapper, iar procesul cu identificatorul 1 este procesul init. Intrucit cuvintul identificator apare frecvent, in continuare acesta va fi prescurtat
la b. ID de proces al parintelui Acesta este ID-ul procesului care a lansat functia fork. c. ID grupului de procese (a nu se confunda cu ID-ul grupului de utilizatori) In UNIX se pot grupa procese legate intre ele. De exemplu, un sistem de gestiune a unei baze de date, poate fi impartit in mai multe procese pentru
a obtine o concurenta in efectuarea operatiilor de I/E. Unul din membrii grupului de procese este liderul grupului. Toate procesele din grupul respectiv vor avea ca ID al grupului de procese valoarea ID al procesului lider. Deci, daca un
proces are ID egal cu cel al grupului de procese, atunci acel proces va fi lider. d. Terminalul de control Este primul terminal deschis de liderul grupului de procese. Normal, terminalul de control pentru procesele unui utilizator este terminalul de la
care a fost lansata comanda login. La formarea unui nou grup, procesele membre ale
noului grup nu mai au un terminal de control. Cind procesul lider de grup s-a
terminat, toate procesele cu acelasi terminal de control primesc semnalul e. ID utilizatorului real f. ID grupului real de utilizatori g. ID utilizatorului efectiv Acest atribut serveste la determinarea drepturilor de acces la fisiere. h. ID grupului efectiv de utilizatori Daca bitul 5 din fig 2 este pozitionat, atunci tot ce s-a spus la punctul g, ramine valabil si aici. Denumirea acestui bit in engleza este biti : 0-3 tipul fisierului Pozitionarea bitului 4 si 5 se poate face prin apelurile de sistem setuid si setgid. Asupra lor se va reveni. i. Dimensiunea limita a fisierelor Atributul acesta exprima dimensiunea maxima a unui fisier creat prin j. Dimensiunea limita a segmentului de date Atributul exprima dimensiunea maxima a segmentului de date al unui proces. k. Valoarea nice Aceasta valoare este folosita in calculul prioritatii unui proces. Aceasta valoare este de obicei intre 0 si 39. Cu cit valoarea sa este mai mare, cu atit prioritatea procesului este mai scazuta. Numai procesele superuser pot da valori negative. Valoarea se poate fixa cu functia de sistem nice. De la crearea unui proces pina la terminarea sa, el trece prin mai multe stari gestionate de nucleu (vezi curs). Starile unui proces Unix Cu exceptia procesului 0, toate celelalte procese sunt create prin apelul functiei de sistem fork. Starea "creat" este o stare de pornire. In urma apelului functiei fork, segmentele parintelui sunt practic dublate, fiind nevoie in acest sens de memorie interna. Daca exista spatiu de memorie interna suficienta, procesul va trece in starea "ready" (gata de executie). In caz contrar va fi trecut in starea "ready suspendat", adica se va gasi in memoria externa (pe dispozitivul swapping). Din starea "ready", planificatorul de procese il va trece in starea "run mod nucleu", unde activitatea functiei fork se va incheia. Trecerea procesului in aceasta stare se va face pe baza de prioritate. Prioritatile sunt dinamice si se calculeaza din secunda in secunda astfel: prioritate=baza+(utilizare_recenta_CPU)/constanta+valoare_nice Se mentioneaza faptul ca rutina ceasului, inafara calculului prioritatii, mai are si alte functii: Planificatorul de procese procedeaza conform urmatorului algoritm: algoritm schedule_proces; input: output: A Cind functia de sistem apelata se termina (initial fork), procesorul va fi trecut in starea "run mod utilizator". Din aceasta stare poate reveni in starea "run mod nucleu" daca apare o intrerupere sau procesul apeleaza o functie de sistem. Cind ceasul emite o interupere catre procesor, procesul care se executa in mod utilizator este trecut in starea "run mod nucleu". Cind handler-ul
de ceas Tema : |
||||||
|
||||||
|
||||||
Copyright© 2005 - 2024 | Trimite document | Harta site | Adauga in favorite |
|