CATEGORII DOCUMENTE |
Un proces isi poate sincroniza executia cu terminarea unui proces fiu prin executia apelului sistem wait. Sintaxa pentru acest apel sistem este:
pid=wait (statIaddr);
unde pid este identificatorul de proces al fiului in starea zombie, iar statIaddr este adresa unui intreg din spatiul utilizator care va contine codul de terminare al procesului fiu.
Figura 8.16 prezinta algoritmul wait. Nucleul cauta un fiu al procesului in starea zombie si daca nu gaseste nici unul intoarce o eroare. Daca gaseste un fiu in starea zombie, extrage identificatorul procesului si parametrul furnizat de apelul sistem exit procesului fiu si intoarce aceste valori la terminarea apelului sistem. Un proces care se termina poate astfel specifica diferite coduri de retur pentru a preciza motivul terminarii sale, dar multe programe nu fac acest lucru in practica. Nucleul adauga timpul acumulat de executia procesului fiu in modurile utilizator si nucleu la campurile corespunzatoare din u area a procesului parinte si in final elibereaza intrarea din tabela de procese ocupata formal de procesul in starea zombie. Aceasta intrare devine disponibila pentru noi procese.
Daca procesul care executa apelulwait are procese fiu, dar niciunul dintre acestea nu se afla in starea zombie, el trece in asteptare la un nivel de prioritate intreruptibila pana la sosirea unui semnal. Nucleul nu contine un apel explicit de trezire a unui proces care asteapta in apelul wait: astfel de procese sunt trezite numai la primirea unor semnale. Pentru orice semnal, cu exceptia semnalului 'terminare fiu' procesul va reactiona dupa cum s-a descris anterior. Cu toate acestea, daca semnalul este 'terminare fiu', procesul ar putea raspunde in mod diferit.
In cazul implicit el va fi trezit din starea de asteptare in apelul wait si va invoca algoritmul issig pentru a verifica daca a receptionat semnale. Algoritmul issig (Figura 8.7) recunoaste cazul special al semnalului 'terminare fiu' si intoarce "fals". Ca urmare nucleul nu executa un apel longjmp din starea de asteptare ci se intoarce in apelul wait. Nucleul va relua bucla din apelul wait, gaseste un fiu in starea zombie -cel putin unul exista- elibereaza intrarea fiului din tabela de procese si iese din apelul sistem wait.
Daca procesul intercepteaza semnalul 'terminare fiu', nucleul apeleaza rutina utilizator de tratare a semnalului, asa cum face pentru alte semnale.
Daca procesul ignora semnalele 'terminare fiu', nucleul reia bucla din apelul wait, elibereaza sloturile din tabela de procese corespunzatoare proceselor fiu aflate in starea zombie si cauta alti fii.
algoritm wait intrari: adresa unei variabile de memorare a starii procesului care se termina iesiri: identificatorul procesului fiu si codul de terminare al acestuia if(procesul nu are fii) return eroare; asteapta la un nivel de prioritate intreruptibita pe evenimentul : terminarea unui proces fiu; } } |
Figura 8.16. Algoritmul pentru wait
De exemplu, un utilizator obtine diferite rezultate cand apeleaza programul din figura 8.17 cu sau fara parametri. Sa consideram mai intai cazul in care utilizatorul apeleaza programul cu un parametru (argc este 1, numele programului). Procesul parinte creeaza 15 procese fiu, care eventual se termina cu codul de retur i, valoarea variabilei din ciclu in momentul crearii procesului. Nucleul executa apelul sistem wait pentru procesul parinte, gaseste un proces fiu in starea zombie si intoarce identificatorul sau de proces si codul lui de terminare. Nu este determinat care din procesele fiu este gasit.
In biblioteca C, procedura pentru apelul sistem exit pastreaza codul de terminare in bitii 8 la 15 ai variabilei retIcode si intoarce identificatorul procesului fiu pentru apelul wait. Astfel variabila retIcode este egala cu 256*i, depinzand de valoarea lui i pentru procesul fiu si variabila retIval este egala cu valoarea identificatorului procesului fiu. Daca utilizatorul apeleaza programul de mai sus cu un parametru (argc>1), procesul parinte apeleaza signal pentru a ignora semnalele " terminare fiu". Sa presupunem ca procesul parinte asteapta in apelul wait inainte ca vreun proces sa se termine: cand un proces fiu se termina, el trimite un semnal "terminare fiu" catre procesul parinte: procesul parinte este trezit, pentru ca asteptarea sa in apelul wait este la un nivel de prioritate intreruptibila. Cand procesul parinte ruleaza, acesta gaseste ca semnalul a fost 'terminare fiu'; dar pentru ca el ignora aceste semnale, nucleul sterge intrarea procesului aflat in starea zombie din tabela de procese si continua executia apelului wait ca si cum nu ar fi existat nici un semnal.
#include <signal.h> main(argc,argv) int argc; char *argv[ ]; ret_val=wait(&ret_code); prinf('valoarea de retur= %x codul de retur= %x n',ret_val, ret_code); } |
Figura 8.18. Exemplu de asteptare si ignorare a semnalelor " terminare fiu"
Nucleul executa procedura anterioara de fiecare data cand procesul parinte receptioneaza un semnal 'terminare fiu' pana cand in final ajunge in bucla apelului wait si constata ca procesul parinte nu mai are fii. Apelul sistem wait intoarce atunci -1. Diferenta intre cele doua apelari ale programului este ca procesul parinte asteapta terminarea unui proces fiu in primul caz si a tuturor proceselor fiu in al doilea caz.
Versiunile mai vechi ale sistemului UNIX implementau apelurile exit si wait fara semnalul 'terminare fiu'. In loc sa trimita semnalul 'terminare fiu', apelul exit trezea procesul parinte. Daca procesul parinte era in asteptare in apelul sistem wait,acesta se putea trezi, gasea un proces fiu in starea zombie si apoi se termina. Daca acesta nu era in asteptare in apelul wait, trezirea nu ar fi avut nici un efect; ar fi gasit un fiu in starea zombie in urmatorul apel wait. In mod similar, procesul init ar fi asteptat in apelul wait si procesele care s-ar fi executat l-ar fi trezit pentru a adopta noi procese aflate in starea zombie.
Problema acestei implementari este imposibilitatea inlaturarii proceselor in starea zombie daca procesul parinte nu executa un apel wait. Daca un proces creeaza mai multe procese fiu dar nu executa niciodata apelul wait, tabela de procese se va umple cu procesele fiu aflate in starea zombie dupa terminarea acestora. De exemplu, sa luam programul din figura 8.18. Procesul citeste din fisierul sau standard de intrare pana cand acesta intalneste sfarsitul de fisier, creand un proces fiu la fiecare citire.
#include <signal.h>
main(argc,argv)
}
Figura 8.18. Exemplu care prezinta motivul implementarii semnalului
'terminare fiu'
Cu toate acestea, procesul parinte nu asteapta terminarea vreunui proces fiu deoarece doreste terminarea cat mai rapida a proceselor fiu iar un proces fiu poate se poate termina dupa un timp indelungat.
Daca procesul parinte executa apelul signal pentru a ignora semnalele 'terminare fiu' , nucleul va elibera intrarile proceselor aflate in starea zombie in mod automat. Altfel, procesele aflate in starea zombie ar putea umple, eventual la maxim, locurile permise in tabela de procese.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1630
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved