Sunteți pe pagina 1din 9

Tema 1

Laborator PATR 2013-2014


Data predarii temei: 9

Studenti:
1.Nichiforov Cristina
2.Sulugiu Madalina
3.Vasile Sorin

Grupa:
333 AC
333 AC
333 AC

mai 2014, ora 24:00

Adresa e-mail:
cristina.nichiforov@gmail.com
madalina.sulugiu@gmail.com
sorin.vasile1609@aut.pub.ro

Observatii:

Grila punctaj
1. Prezentarea problemei propuse spre rezolvare si explicarea abordarii pentru rezolvarea
temei
2. Analiza problemei si evidentierea activitatilor care trebuie abordate in cadrul solutiei
3. Definirea taskurilor care compun aplicatia
4. Prezentarea solutiei de implementare organigramele taskurilor
5. Descrierea modului de sincronizare si evidentierea mecanismelor de sincronizare a
taskurilor
6. Explicarea alegerii solutiei (de ce nu ati utilizat alte mecanisme de sincronizare /
comunicare). Explicarea modului de implementare ce ati ales (procese sau fire de
executie) si de ce?
7. Explicarea modului in care utilizam mecanismele QNX pentru implementarea solutiei
propuse
8. Prezentarea programului complet (sub QNX) care implementeaza solutia pentru problema
propusa (listing) explicatie si comentarii
9. Prezentarea si analiza rezultatelor obtinute prin executia programului
TOTAL:

2p
1p
1p
1p
1p
1p
1p
1p
1p
10 p

Cuprins

TEMA 1...............................................................................................................................................1
1. PREZENTAREA PROBLEMEI PROPUSE.............................................................................................3
2. ANALIZA PROBLEMEI....................................................................................................................3
3. DEFINIREA TASKURILOR................................................................................................................3
4. PREZENTAREA SOLUTIEI DE IMPLEMENTARE.................................................................................3
5. DESCRIEREA MODULUI DE SINCRONIZARE....................................................................................3
6. EXPLICAREA ALEGERII SOLUTIEI..................................................................................................3
7. MECANISMELE QNX PENTRU IMPLEMENTAREA SOLUTIEI............................................................3
8. PREZENTAREA PROGRAMULUI.......................................................................................................3
9. REZULTATELOR OBTINUTE PRIN EXECUTIA PROGRAMULUI...........................................................3
ANEXA LISTING PROGRAM.............................................................................................................4

1. Prezentarea problemei propuse


Sa se implementeze o aplicatie formata din 3 taskuri de tip A (tipareste litera a), B
(tipareste litera b) si C (tiparesc litera c).
Conditiile de tiparire sunt urmatoarele:
un b se scrie intotdeauna inaintea unui c;
b si c trebuie sa alterneze in sir;
numarul de b-uri si c-uri scrise la un moment nu trebuie sa depaseasca numarul de
a-uri.
Sa se implementeze o aplicatie formata din mai multe taskuri, cu mecanismele
specifice QNX, care sa simuleze functionarea specificata.

2. Analiza problemei
Consideram 3 tipuri de cereri ce vor fi testate de catre server odata cu primirea lor:
-Cerere tip A- task-ul A Server,
-Cerere tip B- task-ul B Sever,
-Cerere tip C- task-ul C Server.
Testarea privind starea task-urilor(daca se pot executa sau nu) va fi realizata tot de
server asteptand raspuns din partea task-urilor pentru a putea finaliza tiparirea literelor
respective.
Secvente posibile:
aaabcaaaab
abcaaabc
ab
Secvente imposibile:
aaac nu indeplineste prima conditie
aaabac nu indeplineste a 2-a conditie
abc nu indeplineste a 3-a conditie

3. Definirea taskurilor
Task A - tipareste litera A
Task B - tipareste litera B
Task C - tipareste litera C
Task tip-sever testeaza tipul de cerere si transmite confirmarea la task-uri

4. Prezentarea solutiei de implementare


Task tip-server:
primeste cererea
3

testeaza cererea
trimite mesaj

Task A:
transmite mesaj
primeste raspuns
executa cererea

Task B:
transmite mesaj
primeste raspuns
executa cererea
Task C:
transmite mesaj
primeste raspuns
executa cererea

5. Descrierea modului de sincronizare


Sincronizarea intre server si task-uri(care realizeaza tiparirea literelor) este realizata
prin intermediul mesajelor utilizand functiile specifice: MsgSend(), MsgRecieve() si
MsgReply(). Sincronizarea este stabilita datorita principiului de blocare al acestor functii,
astfel task-ul se blocheaza pana primeste un mesaj de la Server iar Serverul se va bloca
pana va primi reply la mesajul transmis.
Sistemul de transmitere al mesajelor nu se efectueaza direct, ci prin intermediul
conexiunii create intre server si task-ul A, task-ul B si task-ul C. Astfel dupa testarea tipului
de cerere trimitem mesaj catre task-ul A sau B sau C pentru a determina daca task-ul
indeplineste conditia de tiparire a literelor respective sau nu. Iar din partea task-urilor,
odata cu finalizarea cererii trimite reply catre server pentru a putea permite preluarea
urmatoarei cereri.

6. Explicarea alegerii solutiei


Am ales o solutie bazata pe schimbul de mesaje pentru ca sincronizarea prin
intermediul mesajelor este principala forma IPC pusa la dispozitie de nucleul Neutrino.
Astfel, functiile specifice acestei metode permit un schimb de date foarte util, iar principiul
de blocarea pentru send/receive realizeaza o sincronizare puternica intre firele de
executie. Adresarea indirecta folosita prin realizarea conexiunilor si calalelor de transmisie
elimina necesitatea determinarii destinatarului mesajului, determinand optimizarea lucrului
cu cererile pentru oricare din task-uri.

7. Mecanismele QNX pentru implementarea solutiei


Pentru implementarea solutiei propuse am folosit transmiterile de mesaje asa cum
sunt exemplificate in curs si laborator, la fel si privind definirea firelor de executie. Cererile
sunt stocate intr-un vector si vor fi transmise de acolo catre server. Iar taskurile privind
tiparirea de caractere si serverul sunt definite ca mesaje folosind functiile: MsgSend,
MsgRecieve si MsgReply. Un fir de executie care doreste sa primeasca un mesaj creaza
mai intai un canal de comunicatie, iar un alt fir de executie care doreste sa ii trimita un
mesaj trebuie sa creeze o conexiune, prin atasarea la canalul respective. Canalele sunt
folosite de servere pentru a receptiona mesaje.
1. MsgSend() trimite un mesaj si blocheaza firul de executie pana la
confirmare;
2. MsgReceive() asteapta un mesaj pe un anumit canal;
3. MsgReply() confirma receptionarea unui mesaj;
4. ChannelCreate() creeaza un canal de comunicatie;
5. ChannelDestroy() distruge canalul de comunicatie specificat;
6. ConnectAttach() stabileste o conexiune intre un proces si un canal de
comunicatie;
7. ConnectDetach() taie legatura la canalul de comunicatie specificat.

8. Prezentarea programului
Programul creaza cele trei trask-uri de afisare a literelor A, B, C. Fiecare task in
parte trimite un mesaj pe acelasi canal catre server cu cererea de a afisa litera
corespunzatoare. Serverul citeste cate un mesaj aflat in coada, astfel conform conditiilor
impuse in problema raspunde task-ului cu mesajele de confirmare sau infirmare asupra
executiei cererii. Daca s-a primit confirmarea task-ul afiseaza litera. Daca nu, trimite un alt
mesaj cand este disponibil. Serverul continua cu analiza mesajelor primite pe canal si
trimite reply.

Anexa listing program


#include
#include
#include
#include
#include
#include
#include
#include
#include

<stdlib.h>
<stdio.h>
<errno.h>
<string.h>
<unistd.h>
<sys/neutrino.h>
<process.h>
<sys/types.h>
<pthread.h>

int ChID,cID1,cID2,cID3;
int a=0,b=0,c=0,o,flag = 0;
int PIDProces,PID1,PID2,PID3, rcvID;
struct mesaj{
char body[50];
};
void* a_A(void* arg) {
int srv,rcta,i;
char *mesaj_send_a_A = "A?";
struct mesaj *Cmsg, *Smsg;
Cmsg = (struct mesaj*)malloc(sizeof(struct mesaj));
Smsg = (struct mesaj*)malloc(sizeof(struct mesaj));
cID1 = ConnectAttach(0,PIDProces, ChID, _NTO_SIDE_CHANNEL,0);
if (cID1 == -1)
perror("\tClient: eroare conectare.\n");
strcpy(Cmsg->body, mesaj_send_a_A);
srv = MsgSend(cID1, Cmsg, sizeof(struct mesaj), Smsg, sizeof(struct
mesaj));
rcta=MsgReceive(cID1,Cmsg,sizeof(struct mesaj),NULL);
printf("\tPrimit pe A: %s\n",Cmsg->body);
if (Cmsg->body == "OKA")
{
printf("*A*");
a++;
flag = 0;
}
else
{}
sleep(1);
ConnectDetach(cID1);
}
void* a_B(void* arg) {
int srv,rctb,i,cID2;
char *mesaj_send_a_B = "B?";
struct mesaj *Cmsg, *Smsg;
Cmsg = (struct mesaj*)malloc(sizeof(struct mesaj));

Smsg = (struct mesaj*)malloc(sizeof(struct mesaj));


cID2 = ConnectAttach(0,PIDProces, ChID, _NTO_SIDE_CHANNEL,0);
if (cID2 == -1)
perror("\tClient: eroare conectare.\n");
strcpy(Cmsg->body, mesaj_send_a_B);
srv = MsgSend(cID2, Cmsg, sizeof(struct mesaj), Smsg, sizeof(struct
mesaj));
rctb=MsgReceive(cID2,Cmsg,sizeof(struct mesaj),NULL);
printf("\tPrimit pe B: %s\n",Cmsg->body);
if (Cmsg->body == "OKB")
{
printf("*B*");
b++;
flag = 1;
}
else
{}
sleep(1);
ConnectDetach(cID2);
}
void* a_C(void* arg) {
int srv,rctc,i;
char *mesaj_send_a_A = "A?";
struct mesaj *Cmsg, *Smsg;
Cmsg = (struct mesaj*)malloc(sizeof(struct mesaj));
Smsg = (struct mesaj*)malloc(sizeof(struct mesaj));
cID3 = ConnectAttach(0,PIDProces, ChID, _NTO_SIDE_CHANNEL,0);
if (cID1 == -1)
perror("\tClient: eroare conectare.\n");
strcpy(Cmsg->body, mesaj_send_a_A);
srv = MsgSend(cID3, Cmsg, sizeof(struct mesaj), Smsg, sizeof(struct
mesaj));
rctc=MsgReceive(cID1,Cmsg,sizeof(struct mesaj),NULL);
printf("\tPrimit pe C: %s\n",Cmsg->body);
if (Cmsg->body == "OKC")
{
printf("*C*");
c++;
flag = 0;
}
else
{}
sleep(1);
ConnectDetach(cID3);
}
int main() {

pthread_t afisez_A;
pthread_t afisez_B;
pthread_t afisez_C;
pthread_attr_t attr_a;
pthread_attr_t attr_b;
pthread_attr_t attr_c;
int i,n = 0;
struct mesaj *Cmsg, *Rmsg_a,*Rmsg_b, *Rmsg_c;
char *mesaj_a = "OKA";
char *mesaj_b = "OKB";
char *mesaj_c = "OKC";
strcpy(Rmsg_a->body, mesaj_a);
strcpy(Rmsg_b->body, mesaj_b);
strcpy(Rmsg_c->body, mesaj_c);
Cmsg =
Rmsg_a
Rmsg_b
Rmsg_c

(struct mesaj*)malloc(sizeof(struct mesaj));


= (struct mesaj*)malloc(sizeof(struct mesaj));
= (struct mesaj*)malloc(sizeof(struct mesaj));
= (struct mesaj*)malloc(sizeof(struct mesaj));

PIDProces = getpid();
pthread_attr_init( &attr_a );
pthread_attr_init( &attr_b );
pthread_attr_init( &attr_c );
pthread_attr_setdetachstate(&attr_a, PTHREAD_CREATE_JOINABLE );
pthread_attr_setdetachstate(&attr_b, PTHREAD_CREATE_JOINABLE );
pthread_attr_setdetachstate(&attr_c, PTHREAD_CREATE_JOINABLE );
ChID = ChannelCreate(0);
pthread_create(&afisez_A, &attr_a, (void*)&a_A, NULL);
pthread_create(&afisez_B, &attr_b, (void*)&a_B, NULL);
pthread_create(&afisez_C, &attr_c, (void*)&a_C, NULL);
while(n < 10)
{
rcvID = MsgReceive( ChID, Cmsg, sizeof(struct mesaj), NULL);
printf("Am primit de la cient: %s\n", Cmsg->body);
if (Cmsg->body == "A?")
{
if (flag == 0)
MsgReply( rcvID, 0, Rmsg_a, sizeof(struct mesaj));
else
{
MsgReply( rcvID, 0, "NO", sizeof(struct mesaj));
}
}
else if (Cmsg->body == "B?")
{
if (flag == 0)
MsgReply( rcvID, 0, Rmsg_b, sizeof(struct mesaj));
else
{
MsgReply( rcvID, 0, "NO", sizeof(struct mesaj));

}
}
else if (Cmsg->body == "C?")
{
if (flag == 1)
MsgReply( rcvID, 0, Rmsg_c, sizeof(struct mesaj));
else
{
MsgReply( rcvID, 0, "NO", sizeof(struct mesaj));
}
}
n++;
}
if (pthread_join(afisez_A, NULL) != 0){
perror("pthread_join");
return EXIT_FAILURE;
}
if (pthread_join(afisez_B, NULL) != 0){
perror("pthread_join");
return EXIT_FAILURE;
}
if (pthread_join(afisez_C, NULL) != 0){
perror("pthread_join");
return EXIT_FAILURE;
}

pthread_attr_destroy(&attr_a);
pthread_attr_destroy(&attr_b);
pthread_attr_destroy(&attr_c);
ChannelDestroy(ChID);
pthread_exit(NULL);
}

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