Referat, comentariu, eseu, proiect, lucrare bacalaureat, liceu si facultate
Top referateAdmitereTesteUtileContact
      
    


 


Ultimele referate adaugate

Adauga referat - poti sa ne ajuti cu un referat?

Politica de confidentialitate



Ultimele referate descarcare de pe site
  CREDITUL IPOTECAR PENTRU INVESTITII IMOBILIARE (economie)
  Comertul cu amanuntul (economie)
  IDENTIFICAREA CRIMINALISTICA (drept)
  Mecanismul motor, Biela, organe mobile proiect (diverse)
  O scrisoare pierduta (romana)
  O scrisoare pierduta (romana)
  Ion DRUTA (romana)
  COMPORTAMENT PROSOCIAL-COMPORTAMENT ANTISOCIAL (psihologie)
  COMPORTAMENT PROSOCIAL-COMPORTAMENT ANTISOCIAL (psihologie)
  Starea civila (geografie)
 

Ultimele referate cautate in site
   domnisoara hus
   legume
    istoria unui galban
   metanol
   recapitulare
   profitul
   caract
   comentariu liric
   radiolocatia
   praslea cel voinic si merele da aur
 
despre:
 
Sincronizarea in Unix
Colt dreapta
Vizite: ? Nota: ? Ce reprezinta? Intrebari si raspunsuri
 

 

Sincronizarea proceselor in UNIX se poate realiza in doua moduri: controlata de catre sistemul de operare sau controlata de catre utilizator. c4h14hy
In primul caz, mecanismul clasic utilizat este cel de conducta de comunicatie
(pipe). Sincronizarea controlata de utilizator se realizeaza in principal prin intermediul evenimentelor.

Evenimente

Evenimentul este conceptul de baza in sincronizarea si planificarea proceselor UNIX. El reprezinta modalitatea de precizare a momentului in care un proces, anterior blocat (in asteptarea terminarii unei operatii de intrare/ iesire cu terminalul, a eliberarii unei zone tampon sau a unui i-nod), poate trece in starea gata de executie (conditia pe care o asteapta s-a indeplinit).
Blocarea proceselor se face prin intermediul unei functii interne, numita sleep
(a nu se confunda cu functia de biblioteca cu acelasi nume), apelata cu un parametru care reprezinta parametrul principal. In momentul indeplinirii conditiei de deblocare, nucleul, prin intermediul functiei wakeup, trece toate procesele, care asteptau acea conditie, in starea gata de executie. Evident, numai unul dintre acestea se va executa efectiv, celelalte trecand din nou in starea blocat.
Evenimentele sunt reprezentate prin numere intregi, alese prin conventie, astfel incat sa fie chiar adrese virtuale, cunoscute de nucleul UNIX-ului; semnificatia lor este ca sistemul de operare se asteapta ca anumite evenimente sa se mapeze pe anumite adrese ( de exemplu : evenimentul de terminare a unui proces fiu este reprezentat de adresa intrarii corespunzatoare tatalui sau din tabela de procese).
In afara de producerea propriu-zisa a unui eveniment, acest mecanism nu permite si transmiterea altor informatii, cu evenimentul nefiind asociata memorie; el exista doar in momentul in care este folosit.
Dezavantajul acestei abordari consta in faptul ca sincronizarea nu se poate face in functie de o anumita cantitate de informatie. De exemplu, toate procesele care au facut cerere de memorie vor fi planificate pentru executie la eliberarea unei zone, indiferent de dimensiunea acesteia, desi zona eliberata s-ar putea sa nu fie suficienta pentru multe dintre ele si deci sa fie nevoite sa treaca din nou in asteptare (in realitate, exista un singur proces care cere memorie, swapper-ul, iar el va fi activat de catre nucleu la eliberarea unei zone de memorie chiar daca aceasta nu este suficienta). De asemenea, daca un proces se blocheaza in asteptarea unui eveniment care s-a produs deja, nu exista nici o posibilitate de a specifica acest lucru prin intermediul evenimentelor.
In cadrul sincronizarii intre procese prin intermediul evenimentelor, se pot identifica mai multe situatii : sincronizarea prin semnale, sincronizarea intre un proces tata si fii sai, sincronizarea prin intermediul unor functii de sistem.




Semnale

Aparitia unor evenimente in sistem este semnalata in UNIX fie de catre nucleu, prin intermediul functiei wakeup, fie prin intermediul semnalelor.
Acestea din urma sunt implementate cu ajutorul unor biti, memorati in tabele de procese si care pot fi setati fie de catre nucleu (in cazul producerii unor evenimente legate de hardware), fie de catre utilizator (prin apelul directivei kill).
Nucleul verifica primirea unui semnal (setarea bitului corespunzator acestuia) la trecerea din mod sistem in mod utilizator, precum si inaintea si dupa blocarea unui proces. Tratarea semnalelor se face in contextul procesului care le primeste.
Semnalele nu transfera cantitate de informatie proceselor, ci sunt forme de sincronizare (functie de tipul semnalului, 19 standard in Unix V).
Cind un semnal ajunge la un proces, el este intrerupt din activitatea curenta si obligat sa raspunda. Avem : a)procesul poate ignora semnalul, continuindu-si activitatea (SIGKILL nu poate fi ignorat). Sistemul isi pastreaza posibilitatea de a termina procesul. b)procesul poate lasa sistemul sa execute actiunea implicita (valabil pentru toate semnalele de terminare a proceselor, exceptie facind doar SIGCLD si
SIGPWR care sunt explicit ignorate). c)procesul isi poate defini o procedura proprie de tratare a semnalului, care va fi automat lansata la sosirea acestuia (handler).
Indiferent de modul cum reactioneaza programul la un anumit semnal, dupa terminarea actiunii, daca nu era ignorat, semnalul este resetat pentru viitor la actiunea implicita, excluzind semnalele SIGKILL si SIGTRAP care sunt generate foarte des si ar fi ineficienta resetarea lor de fiecare data. Apelul signal() comunica sistemului care este actiunea dorita de proces pentru un anumit semnal.

#include <signal.h> void (* signal(semnal,functie))(int); int semnal; void (* functie)(int);

Parametrul semnal reprezinta semnalul referit si "functie" functia de tratare a lui. Functiile de tratare nu intorc valori si au ca parametru unic numarul semnalului sosit. Exista 2 valori implicite pentru functia de tratare,
SIG_IGN (ignorarea semnalului de catre proces) si SIG_DFL (resetarea functiei la valoarea implicita). Apelul signal intoarce vechea functie de tratare (poate fi SIG_IGN sau SIG_DFL) sau -1 in cazul cind ceva nu este corect (numar semnal incorect, se incearca ignorarea lui SIGKILL, etc.). Aceasta valoare se defineste:

#define BADSIG (void (*)(int))-1

Valoarea returnata de signal poate fi folosita pentru a restaura starea anterioara apelului, dupa ce se iese din zona critica. Programul de mai jos arata cum putem ignora semnalele SIGINT si SIGQUIT intr-o regiune a programului in care este periculos sa se termine anormal (functia ignoraint() si refaint()).

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>

static void (* intvechi)(int),(* quitvechi)(int);
#define BADSIG (void (*)(int))-1

void ignoraint ()
A static int first=1; if (first) /* doar prima data salvam starea */
A first=0; intvechi=signal(SIGINT,SIG_IGN); quitvechi=signal(SIGQUIT,SIG_IGN); if (intvechi==BADSIG || quitvechi==BADSIG) perror("signal");
S else if(signal(SIGINT,SIG_IGN)==BADSIG||signal(SIGQUIT,SIG_IGN)==BADSIG) perror ("signal");
S void refaint()
A if(signal(SIGINT,intvechi)==BADSIG||signal(SIGQUIT,quitvechi)==BASSIG) perror("signal");
S

void main(argc,argv) /* inlocuieste in fisierul de pe linia */
/* de comanda caracterele mici cu mari */ int argc; char **argv;
A
FILE *in, *out; char buffera256i; // buffer comand_ UNIX char *p;
// parte de cod care poate rula cu intreruperile activate if (argc!=2)
A printf("Argumente gresite !\n"); exit(1);
S in=fopen(argva1i,"r");//atribut read out=fopen("temporar","w"); if (!in || !out)
A printf("Nu se pot deschide fisierele !\n\a"); exit(1);
S
while(fgets(buffer,256,in))
A p=buffer;
while(*p) //converteste bufferul la caractere mari
A
*p=toupper(*p); p++;
S fputs(buffer,out);
S fclose(in); fclose(out); ignoraint();
/* sectiune critica */ unlink(argva1i); rename("temporar",argva1i); refaint();
/* terminare sectiune critica */
S

Apelurile definite intr-un proces se pastreaza si in fiu in urma apelului fork(). In cazul apelului exec() se pastreaza doar semnalele setate pe
SIG_IGN si SIG_DFL. Cele care au atasata o functie a utilizatorului se reseteaza la valoarea SIG_DFL (in cazul exec se incarca un nou program si segmentul de cod al procesului este modificat si evident vechile rutine de tratare a semnalelor ori nu se regasesc ori sunt la alte adrese).
Semnalele sosite catre un proces nu sunt introduse in nici o coada de asteptare (daca au fost ignorate s-au pierdut). Singura exceptie este SIGCLD care asteapta pina procesul parinte executa apelul wait() pentru a lua cunostinta de terminarea procesului fiu (uneori fiul se termina inainte ca parintele sa execute wait()). Daca semnalul n-ar fi memorat, procesul parinte ar fi blocat pina la terminarea unui alt fiu! SIGCLD nu este memorat in cazul in care parintele a setat explicit pe valoarea SIG_IGN rutina de tratare a semnalului. Datorita faptului ca semnalele ignorate se pierd, aceasta forma de sincronizare comunicare nu este prea folosita. In cazul cind procesul are de executat mai multe operatii la terminare (stergerea fisierelor temporare, restaurarea unui fisier incomplet prelucrat) procesul trebuie sa intercepteze semnalele SIGHUP,

SIGINT si SIGTERM si pe ele sa execute operatiile de curatire. De asemenea, pe parcursul dezvoltarii unei aplicatii, semnalul SIGQUIT nu trebuie interceptat, pentru a putea termina procesul cu CTRL \ insotit de core dump. Dar in cazul unui proces care lucreaza in background (lansat cu &) acesta ruleaza cu semnalele SIGINT si SIGQUIT implicit ignorate, pentru a nu fi intrerupt accidental de apasarea tastelor de intrerupere. In acest caz rutina de tratare a acestor semnale trebuie sa ramina SIG_IGN. Rutina setsig din exemplul de mai jos seteaza semnalul doar in situatia cind nu a fost anterior ignorat. Exista si o rutina de terminare anormala a unui proces.

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#define BADSIG (void (*)(int))-1 void seteaza_semnal(semnal,functie) int semnal; void (*functie)(int)
A void (*sigvechi)(int); sigvechi=signal(semnal,SIG_IGN); if(sigvechi==BADSIG) perror("signal"); else if(sigvechi==SIG_IGN) return; else if(sigvechi!=SIG_DFL)
A printf("Semnalul era deja captat!\n"); exit(1);
S if(signal(semnal,functie)==BADSIG) perror("signal");
S

void capteaza_semnale()
A void curata(); seteaza_semnal(SIGHUP,curata); seteaza_semnal(SIGINT,curata); seteaza_semnal(SIGQUIT,curata); seteaza_semnal(SIGTERM,curata);
S

void curata(semnal) int semnal;
A if(signal(semnal,SIG_IGN)==BADSIG) perror("signal"); if(unlink("temporar")==-1) perror("unlink"); switch(semnal)
A case SIGHUP: fprintf(stderr,"Hangup \n"); break; case SIGINT: fprintf(stderr,"Interrupt \n"); break; case SIGQUIT: fprintf(stderr,"Quit \n"); break;
S exit(1);
S int main(argc,argv) int argc; char **argv;
A
FILE *file; int i; if(argc!=2)
A printf("Argumente gresite !\n\a"); exit(1);
S capteaza_semnale(); file=fopen("temporar","w"); if(!file)
A printf("Nu pot deschide fisierul temporar !\n"); exit(1);
S for(i=0;i<10000;i++) fprintf(file,"Articol: %5d\n",i); fclose(file); rename("temporar",argva1i); return 0;
S

La sosirea unui semnal este terminat cu eroare orice apel sistem care asteapta, lansat anterior de proces. De exemplu, daca procesul a lansat o citire read, la venirea unui semnal acesta se intoarce cu -1 (in acest caz variabila errno primeste valoarea EINTR). Controlul acestor situatii nu este simplu si se apeleaza la solutii globale: folosirea rutinelor setjmp, longjmp.

#include <setjmp.h>

int setjmp(jmpenv) jmp_buf jmpenv;

void longjmp(jmpenv,valoare) jmp_buf jmpenv; int valoare;

Rutina setjmp creeaza un punct de intoarcere salvind in bufferul jmpenv starea curenta a procesului, in asa fel ca la apelul rutinei longjmp sa para ca tocmai setjmp s-a intors din apel. Rutina longjmp restaureaza starea salvata de setjmp si defineste valoarea cu care setjmp se va intoarce. La prima revenire din setjmp, atunci cind se salveaza starea, functia intoarce valoarea 0, fata de celelalte reveniri cauzate de apelul lui longjmp care au valoarea diferita 0.
In exemplul de mai jos este o tehnica folosita de editorul vi care sta in permanenta in asteptarea unei taste. Daca apasam in modul introducere al editorului tasta DEL aceasta activeaza ca si ESC, pentru ca un apel de longjmp ne trimite in bucla principala de citire, in modul comanda al editorului.

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h> static jmp_buf jmpbuf;
#define BADSIG (void(*)(int))-1

void jumper(int c)
A longjmp(jmpbuf,1); printf("longjmp n-ar trebui sa revina\n"); exit(1);
S

void bucla_principala()
A int i; for(i=1; i!=0; i++) printf("%d wait\r",i);
S

main()
A int nr; char buffera256i; if(signal(SIGINT,SIG_IGN)!=SIG_IGN)
A if(setjmp(jmpbuf)!=0) printf("\n intrerupere \n"); if(signal(SIGINT,jumper)==BADSIG perror("signal");
S bucla_principala();
S

Se poate trimite un semnal catre un proces cu ajutorul apelului kill.

int kill(pid,semnal); int pid; int semnal;

Parametrul pid este numarul de identificare al procesului, iar semnal reprezinta numarul semnalului pe care vrem sa-l trimitem. Daca pid=0, semnalul va fi trimis tuturor proceselor din acelasi grup cu procesul care lanseaza apelul. Aceasta proprietate poate fi folosita pentru a termina toate procesele care ruleaza in background lansate de la un terminal. Daca pid=-1, semnalul este trimis catre toate procesele care au uid-ul real (userid) egal cu cel al pprprietarului procesului care a lansat apelul. Aceasta foloseste la terminarea tuturor proceselor care apartin unui user indiferent de grupul din care fac parte (cite terminale). Daca supervisorul executa kill cu pid=-1, toate procesele din sistem vor fi terminate cu exceptia lui 0 si 1 (init, swap). Daca pid < -1, semnalul este trimis tuturor proceselor care au numarul de grup egal cu valoarea absoluta a lui pid. In practica nu se foloseste kill ca apel sistem, ci ca comanda.

Un proces poate sa-si intrerupa activitatea cu pause() in asteptarea unui semnal: void pause(). La iesirea din pause() procesul nu poate sti ce semnal a cauzat intreruperea, iar errno este setata pe valoarea EINTR. Cea mai utila folosire a acestui apel sistem este asteptarea unui semnal de alarma setat de apelul alarm.

unsigned alarm(secunde); unsigned secunde;

Parametrul reprezinta numarul de secunde dupa care procesul porneste semnalul SIGALRM. Valoarea rezultata este vechea valoare a ceasului (pentru fiecare proces este un ceas, un nou apel al functiei alarm distruge vechea valoare). Daca procesul se razgindeste intre timp el poate inhiba semnalul prin alarm(0).

#include<stdio.h>
#include<signal.h>
#define BADSIG (void(*)(int)) -1

void sleep2(secunde) int secunde;
A if(signal(SIGALRM,nimic)==BADSIG) perror("signal"); alarm(secunde); pause();
S void nimic(semnal); int semnal;

main()
A printf("Se asteapta 5 secunde !\n"); sleep2(5); printf("Thank you !\n");
S

Tabelul semnalelor definite in UNIX V (asa cum este definit in
/usr/include/signal.h).

SIGHUP(1) Hangup. Acest semnal este trimis, atunci cind un terminal este oprit
(conexiunea este intrerupta), catre fiecare proces care apartine terminalului respectiv. El este trimis si atunci cind procesul parinte al unui grup de procese este terminat, oricare ar fi motivul. Acest proces ne da posibilitatea sa simulam intreruperea conexiunii chiar daca terminalul nu este conectat la distanta.

SIGINT(2) Interrupt. Acest semnal este trimis unui proces atunci cind la terminalul asociat procesului s-a apasat tasta de intrerupere (de obicei DEL).
Tasta de intrerupere poate fi dezactivata sau poate fi modificata prin apelul ioctl. Atentie, aceasta situatie nu este echivalenta cu ignorarea semnalului.

SIGQUIT(3) Quit. Semnalul este similar cu SIGINT, dar este generat la apasarea tastei CTRL \. La terminarea procesului se creeaza o imagine a starii procesului pe disc pentru verificari ulterioare.

SIGILL(4) Illegal instruction. Acest semnal este trimis procesului cind hw detecteaza o instructiune ilegala. Este generat de obicei pe calculatoare fara coprocesor de VM o rutina soft interceptand semnalul si executia instructiunii.

SIGTRAP(5) Trace trap. Semnalul se trimite dupa fiecare instructiune daca procesul are activata optiunea de trasare. Este folosit de debuggere sistem.

SIGIOT(6) I/O trap instruction. Acest semnal este trimis cind se semnaleaza o problema hw (semnificatia este dependenta de tipul masinii). Semnalul este folosit de functia abort pentru a provoca terminarea procesului cu salvarea starii pe disc.

SIGEMT(7) Emulator trap instruction. Semnalul este trimis cind apar unele probleme hard (rar).

SIGFPE(8) Floating point exception. Trimis atunci cind hw detecteaza o problema de lucru cu sistemul de VM, de exemplu cind se incearca folosirea unui numar care are un format incorect de reprezentare.

SIGKILL(9) Kill. Acest semnal este singurul mod sigur de a termina un proces
(nu poate fi ignorat). Se foloseste numai in caz de urgenta (de obicei este preferat lui SIGTERM(15)).

SIGBUS(10) Bus error. Semnal dependent de masina (cind se adreseaza o adresa impara a unei structuri de date ce trebuie sa se afle la o adresa de cuvint).

SIGSENV(11) Segmentation violation. Dependent de masina (cind se incearca adresarea datelor din afara spatiului de adrese).

SIGSYS(12) Bad argument to DSystem Call. Nu se utilizeaza acum.

SIGPIPE(13) Write on pipe not open for reading. Semnalul este trimis procesului atunci cind acesta incearca sa scrie intr-un canal de comunicatie din care nu citeste nimeni (se poate folosi pentru terminarea unei intregi inlantuiri de pipe). Daca un proces se termina anormal toate celelalte primesc acest semnal in cascada.

SIGALRM(14) Alarm clock. Semnalul este trimis procesului cind ceasul sau a ajuns intr-un moment fixat (fixarea se face cu apelul alarm).

SIGTERM(15) Software termination. Se opreste un proces. Comanda kill trimite implicit acest semnal. Un proces care intercepteaza acest semnal trebuie sa execute la primirea lui operatiile de salvare si curatire necesare, dupa care se apeleaza exit.

SIGUSR1(16) User defined signal 1. Acest semnal poate fi folosit de procese pemtru a comunica intre ele (nu prea este utilizat).

SIGUSR2(17) User defined signal 2. Idem.

SIGCLD(18) Death of a child. Este primit de parinte cind unul din fii s-a terminat (actioneaza diferit fata de celelalte deoarece este pus intr-o coada de asteptare).

SIGPWR(19) Power fail restart. Depinde de implementare (apare cind scade tensiunea de alimentare). Procesul poate sa-si salveze starea si sa apeleze exit sau isi salveaza starea si apeleaza sleep (daca se mai trezeste).

Tema :
-sa se exerseze procese ce se sincronizeaza prin semnale


Colt dreapta
Creeaza cont
Comentarii:

Nu ai gasit ce cautai? Crezi ca ceva ne lipseste? Lasa-ti comentariul si incercam sa te ajutam.
Esti satisfacut de calitarea acestui referat, eseu, cometariu? Apreciem aprecierile voastre.

Nume (obligatoriu):

Email (obligatoriu, nu va fi publicat):

Site URL (optional):


Comentariile tale: (NO HTML)


Noteaza referatul:
In prezent referatul este notat cu: ? (media unui numar de ? de note primite).

2345678910

 
Copyright© 2005 - 2024 | Trimite referat | Harta site | Adauga in favorite
Colt dreapta