Documente noi - cercetari, esee, comentariu, compunere, document
Documente categorii

Procese si threaduri in unix

PROCESE SI THREADURI IN UNIX


1. Procese in UNIX


In sistemul de operare UNIX fiecare proces are un identificator numeric, numit identificator de proces PID. Acest identificator este folosit atunci cand se face referire la procesul respectiv din interiorul programelor sau prin intermediul interpretorului de comenzi.

Doua apeluri simple permit aflarea PID-ului procesului curent si al parintelui acestuia:

getpid(void) - pentru procesul curent;

getppid(void) - pentru procesul parinte.

Creerea unui proces se face prin apelul sistem:

fork()

Prin aceasta functie sistem, procesul apelant, numit parinte, creeaza un nou proces, numit fiu, care va fi o copie fidela a parintelui. Procesul fiu va avea:



-propria lui zona de date,

-propria lui stiva,

-propriul sau cod executabil,

toate fiind copiate de la parinte, in cele mai mici detalii.

O modalitate de utilizare a apelului fork() este de a imparti codul unui proces in doua sau mai multe procese care se vor executa in paralel. Acest lucru este utilizat in proiectarea si rularea proceselor si programelor paralele.

Exemplul 1.

Proces parinte

i1

i2

i3



ik

momentul

apelului fork() Proces fiu

ik+1 ik+1

ik+2 ik+2


in in


Exemplul 2

Se da urmatoarea secventa de program:

fork();printf("An");

fork();printf("Bn");

fork();printf("Cn");

Presupunand ca toate apelurile functiei fork() se executa cu succes, se cere:

-Cate procese sunt create ?

-Sa se traseze arborele parinte - fiu al proceselor create.

-Cate linii de text vor fi afisate la iesirea standard ?

-Este posibil ca linia cu textul "B" sa fie afisata inaintea liniei cu textul "A" ?

Sunt create 7 procese, plus procesul initial, vor fi 8 procese. Cifrele arata dupa al cateleafork() au fost create. Dupa primul fork()se creeaza procesul cu cifra 1. Se va scrie A atat in procesul initial cat si in cel final. Dupa al doilea fork(), se creeaza procesul fiu notat cu cifra 2, adica fiecare proces creat pana acum va avea cate un fiu, notat cu 2. Dupa al treilea fork(), fiecare proces creat pana acum va crea cate un nou fiu, notat cu 3. In general dupa nfork() ,se produc 2n-1 fii.


A



B

C


A

B B C

CC



BCC

C


C


Fig.3.4.Structura arborescenta a proceselor.


Fiecare proces afiseaza liniile de text care urmeaza momentului crearii sale:

linia care scrie "A" este afisata de 21 ori;

linia care scrie "B" este afisata de 22 ori;

linia care scrie "C" este afisata de 23 ori.

Numarul total de linii afisate este 21+22+23=14

In ceea ce priveste ordinea de afisare a celor 14 linii, intervine nedeterminarea provenita din faptul ca nu se stie cine va fi executat primul, parintele sau noul fiu creat. Valoarea returnata de fork() este:

-1, eroare, operatia nu s-a putut executa;

0,in codul fiului;

pidf, in codul parintelui, unde pidf este identificatorul de

proces al fiului nou creat.

Pana acum am vazut ca prin simplul apel al functiei fork() se creeaza un proces identic cu procesul parinte. Pentru a crea un nou proces care sa ruleze un program diferit de cel al parintelui, se vor folosi functiile de tipul exec(), execl(), execlp(), execv(), execvp(), execll(), execvl(). Toate aceste functii primesc ca parametru un nume de fisier care reprezinta un program executabil si recicleaza lansarea in executie a programului. Programul va fi lansat astfel incat se va suprascrie codul, datele si stiva procesului care apeleaza exec(), asa ca, imediat dupa acest apel, programul initial sa nu mai existe in memorie. Procesul va ramane, insa, identificat prin acelasi PID si va mosteni toate eventualele redirectari facute in prealabil asupra descriptorilor de fisier.

In concluzie, lansarea intr-un proces separat a unui program se face apeland fork()pentru crearea noului proces, dupa care, in portiunea de cod executata de fiu, se va apela una din functiile exec().

In UNIX un proces se poate termina in mod normal sau anormal.

Terminarea normala poate fi realizata prin:

-revenire naturala;



-apelul sistem de tip exit().

Terminarea anormala se produce cand:

-se apeleaza abort();

-procesul primeste un semnal.

In marea majoritate a versiunilor UNIX, exista doua apeluri de terminare normala: exit(), exit().Principalul rol al apelului exit() este sa asigure la terminarea procesului tratarea corespunzatoare a operatiilor de introducere /extragere , golirea tampoanelor utilizate pentru acest proces si inchiderea tuturor fisierelor deschise. _exit() produce direct revenirea in nucleu, fara operatiile de la functia exit().

Din cele prezentate pana acum, nu se poate spune nimic despre sincronizarea parinte-fiu, adica despre cine termina primul sau cine se executa primul. Apelurile wait() si waitpid() vin in intampinarea acestui neajuns. wait() este folosita pentru asteptarea de catre parinte a fiului, deci se executa mai intai fiul si apoi parintele. waitpid() este folosita pentru asteptarea unui proces oarecare.

In UNIX procesele au un caracter dinamic. Ele se nasc, evolueaza in sistem putand da nastere altor sisteme, si dispar. In felul acesta se creeaza o ierarhie dinamica de procese in sistem, care incepe cu procesul 0 (swapper), continua cu procesul 1 (init), proces ce da nastere unor procese fiu. Procesul cu identificatorul 2, proces sistem, apare la unele implementari sub denumirea de pagedaemon  si este responsabil de suportul pentru memorie virtuala. Terminarea fortata a executiei unui proces se realizeaza cu comanda kill(optiuni)(pid).

In general, in executia parinte -fiu, exista doua situatii:

-a) fiul se termina inaintea parintelui;

-b) parintele se termina inaintea fiului.

In primul caz, intre momentul in care se termina fiul si momentul in care el este distrus, procesul fiu este in starea zombie. De obicei, dupa terminarea executiei fiului, parintele executa un wait() si scoate fiul din starea zombie.

In al doilea caz, in momentul terminarii parintelui, nucleul SO este acela care examineaza daca parintele a avut copii. Daca da, parintele nou al acestor fii va fi procesul init(), nelasand fiii in starea zombie.

Revenind la starile unui proces, sistemul de operare UNIX distruge urmatoarele stari de baza:

-executie in mod utilizator (USER);



-executie in mod nucleu (KERNEL);

-gata de executie (READY);

-in asteptare (BLOCAT)

-zombie.


2. Threaduri in UNIX


In UNIX-ul traditional nu sunt definite threadurile. Ele au aparut odata cu standardul POSIX care asigura portabilitatea intre platforme hard diferite. Iata o comparatie intre procesele UNIX si threadurile POSIX (pthread):



Caracteristica

Procese UNIX

Pthreaduri POSIX

portabilitate

fork()standard

interfata standard portabilitate

Cost de creare

Mare

Relativ mic

Cost de comutare

Mare

Foarte mic

Spatiu de achesa

Separat

Partajat

Memorie partajata

Partajare explicita

Partajare implicita

Obiecte de excludere mutuala

Semafoare, mutexuri UNIX

Semafoare, mutexuri POSIX

Fisiere si stringuri de I/O

Tabele de fisiere separate

Tabele de fisiere unice

Un pthread se creeaza cu ajutorul functiei

int pthread create (lista de parametri).