Sunteți pe pagina 1din 23

PR OG R A M A R E A A PLIC A TIILOR IN TIM P R E A L

Curs 8

- Semnale-

Cuprins curs 8:

semnale

un mecanism asincron de tratare a evenimentelor

Semnale:

spre deosebire de mesaje, semnalele sunt indicatoare complet asincrone ale evenimentelor care apar in sistem semnalele mai sunt denumite si intreruperi software, deoarece pot schimba fluxul normal de executie al programului la orice moment de timp si in orice loc al executiei

semnalele pot fi generate intr-un proces ca urmare a unei erori (de exemplu, impartire la zero), a unui eveniment (de exemplu, se tasteaza CTRL-C), sau atunci semnalul este generat de catre un proces (de exemplu, cu functia kill())

Semnale:

semnalele trebuie "tratate" in mod special de procese rutine de tratare a semnalelor (engl. signal handlers) cei trei pasi de procesare asociati semnalelor sunt generarea semnalelor transmiterea semnalelor tratarea semnalelor

Semnale (exemplu QNX):

Semnale:

Exista trei modalitati in care un proces poate lua in considerare un semnal: procesul poate trata semnalul prin definirea unei functii speciale (engl. signal-handler) care sa fie apelata si sa prinda (catch a signal) semnalul de fiecare data cand acesta este primit; procesul poate ignora in mod explicit semnalul (caz in care semnalul este pierdut), nefiind executata nici o actiune; procesul accepta semnalul in mod implicit, si in acest caz se aplica actiunea default, care in mod normal presupune terminarea procesului

Semnale:

exista un numar predefinit de semnale, fiecaruia fiindu-i alocat un numar intreg exista, de asemenea, un numar de semnale definite de utilizator ce pot fi folosite in aplicatii semnalele sunt identificate prin nume si numar unele semnale sunt asociate evenimentelor care le-au generat (de exemplu, SIGINT, generat de o intrerupere de la tastura) altele nu au asociate evenimente predefinite (de exemplu, SIGUSR1). detalii despre semnale sunt disponibile in biblioteca QNX signal.h exemplu QNX: s-a definit SIGRTMIN pentru primul semnal de timp real si SIGRTMAX pentru ultimul semnal de timp real doar semnalele ale caror numere se afla intre SIGRTMIN si SIGRTMAX sunt considerate semnale POSIX de timp real

Semnale (exemplu QNX):

"Programarea Aplicatiilor in Timp-Real", cap. 5, pag. 151

Semnale:

un semnal poate

fi livrat (delivery) imediat procesului caruia ii este destinat poate fi blocat (mai tarziu, despre masti de semnal) si livrat mai tarziu

un semnal blocat intra in starea de asteptare a livrarii (este pending)

standardul POSIX include conceptul de asezare in coada a semnalelor de timp-real

Semnale generarea semnalelor sub QNX:

Modalitatile prin care un proces poate genera un semnal care va fi trimis unui alt proces sunt urmatoarele: prin intermediul functiei kill(); cu ajutorul functiei sigqueue(). Aceasta functie poate trimite numai semnale de timp real; cu ajutorul functiei raise().

Pentru a transmite un semnal:

oricarui proces:

kill(pid_t pid, int signo) sigqueue(pid_t pid, int signo, union sigval value) necesita permisiunea sender-ul trebuie sa fie root sau acelasi user ca si procesul target

catre acelasi proces:

raise (int signo)

unui fir din cadrul aceluiasi proces:

pthread_kill(pthread_t tid, int signo);

Semnale tratarea semnalelor sub QNX:

actiunea default a celor mai multe semnale este aceea de a termina (engl. kill ) procesul care le primeste, dar este posibil ca aceast comportament implicit sa fie evitat prin folosirea unor handlere se semnal dedicate, definite de programatorul aplicatiei multe semnale sunt generate de erori serioase, cum ar fi cele de memorie sau de caderea tensiunii de alimentare

aceste erori nu pot fi remediate si nu se poate face mare lucru pentru a le evita

pe de alta parte, anumite semnale (de exemplu, SIGCONT) sunt benigne si sunt utilizate doar pentru a atentiona utilizatorul in privinta unui anumit eveniment

Semnale tratarea semnalelor sub QNX:

o rutina de tratare a semnalului primeste ca parametru doar numarul semnalului receptionat de proces. Orice alta informatie de care este nevoie va fi dedusa din setarile programului (e.g. din variabilele globale: void sig_handler(int sig_no){ if(sig_no == SIGSEGV){ // executa o anumita operatie // } ++sig_count; }

variabila sig_count trebuie sa fie declarata in programul principal, astfel: static volatile sig_atomic_t sig_count = 0;

ceea ce garanteaza faptul ca poate fi modificata in siguranta

Semnale tratarea semnalelor sub QNX:

in general, procesarea semnalelor prin intermediul rutinelor de tratare a semnalelor (handlere de semnal) presupune trei pasi:

definirea semnalului care va fi procesat in rutina; declararea rutinei de tratare a semnalului; instalarea rutinei de tratare a semnalului (cu functia sigaction()).

Semnale tratarea semnalelor sub QNX:

#define MySig <nr_semnal> // declara handler semnal void handler(int signo, <alti_parametri>){ switch(signo){ case ... : .... case MySig: executa_ceva(); // continua executia taskului din punctul in care a fost intrerupt break; default: break; } } main(){ instaleaza_handler_semnal(handler); ... executa_operatii(); ... }

Semnale tratarea semnalelor sub QNX (exemplu):


#include #include #include #include #include <stdio.h> <unistd.h> <process.h> <signal.h> <errno.h>

static volatile sig_atomic_t sig_count = 0; void sig_handler(int sig_no){ if( sig_no == SIGALRM) printf("A expirat alarma! \n"); else if(sig_no == SIGSEGV){ printf("Segment violation! \n"); signal(SIGSEGV, SIG_DFL); } else if(sig_no == SIGCHLD) printf("S-a terminat procesul fiu! \n"); else if(sig_no == SIGINT) printf("Break ! \n"); else if(sig_no == SIGUSR1) printf("Semnal de la user ! \n"); ++sig_count; }

Semnale tratarea semnalelor sub QNX (exemplu):


main(void) { int n; void sig_handler(int); signal(SIGALRM, sig_handler); /*signal(SIGSEGV, sig_handler);*/ signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); signal(SIGUSR1, sig_handler); alarm(10); if(spawnl(P_NOWAIT, "./ex_schild.out", "./ex_schild.out", NULL) != 1) for(n=20; n; ) n = sleep(n); printf("%d semnale \n", sig_count); } *((char*)1) = 0; /* genereaza o ultima eroare */

Semnale tratarea semnalelor sub QNX (exemplu):

/* ex_schild.c */ #include <stdlib.h> #include <unistd.h> main(void){ printf("Proces fiu ... \n"); sleep(5); exit(123); }

Semnale tratarea semnalelor sub QNX (exemplu):

semnalul cu numarul 16, SIGUSR1, poate fi transmis din alt terminal, cu comanda:

# slay -sUSR1 signal.out

OBSERVATIE:

deoarece linia de cod care trateaza semnalul SIGSEGV este comentata, procesul, nu va putea trata acest semnal in rutina si se va termina fortat

eroarea primita este:

# Memory fault (core dumped)

Exemplul problema:

Enunt problema: Un cont bancar este utilizat de mai multe persoane (procese). Fiecare persoana poate depozita sau retrage anumite sume de bani din contul comun. Sa se scrie o aplicatie multitasking care va fi formata din urmatoarele tipuri de taskuri:

task depunere: va depune o suma in contul comun (va face o cerere de depunere); task retragere: va incerca sa retraga o suma de bani din contul comun (va face o cerere de retragere); task server: va monitoriza situatia depunerilor / retragerilor in/din contul comun, astfel incat balanta (suma depunerilor minus suma retragerilor, la zi) sa nu fie negativa.

Exemplul:

Cerinte:

sa se analizeze problema si sa se propuna o solutie pentru implementare sa se defineasca taskurile sa se organizeze aplicatia sub forma organigramelor sa se aleaga un mecanism de sinronizare / comunicare (sub QNX) pentru implementare sa se schiteze programul cu functii specifice sub QNX

Exemplul:

presupunem ca un singur task depune, unul singur retrage, si un alt task monitorizeaza balanta cum gandim: dam prioritate taskului(lor) care depune in cont, apoi lasam sa retraga, daca sunt bani suficienti; taskul de monitorizare decide cine depune si cine retrage facem organigramele (toate taskurile se executa in bucla infinita) de exemplu, alegem o solutie cu semafoare

Exemplul:

Task depunere

Task monitorizare

Task retragere

Task initializare

P(SemD)

P(GataD)

P(SemR) incearca sa retraga

init SemD =1 init GataD =0 init SemR =0 init GataR = 0

depune

V(SemR)

V(GataD)

P(GataR)

V(GataR)

V(SemD)

S-ar putea să vă placă și