PDA

View Full Version : [C]matrice statica,dinamica,memoria condivisa


viridovix1
16-08-2005, 16:16
Sistema Suse 9.2, linguaggio C , compilatore gcc.
Ho realizzato un sistema di prenotazione posti per una sala cinematografica, con un processo su una macchina server che gestisce la mappa dei posti.
Ogni posto è caratterizzato da numero di fila, numero di poltrona e da un flag che indica se il posto è prenotato o meno.
Il server accetta e processa sequenzialmente le richieste prenotazioni di posti da uno o piu' client che possono essere sulla stessa macchina o in remoto(quindi macchine diverse).

Come struttura ho utilizzato una matrice statica [3][3]
Con un unico client funziona tutto perfettamente , ma quando si connette un secondo client ,questo visualizza una matrice che nn tiene conto delle prenotazioni effettuate dal primo client, e la stessa cosa vale per il primo client.
Quindi i vari client nn fanno riferimento alla stessa matrice:(
All'inizio pensavo che dipendesse dalla posizione dell chiamata alla funzione inizializza(cinema) , ma quando il secondo client si connette questa nn dovrebe essere chiamata.

Ecco il codice del main del server:



//main server
int main(int argc,char *argv[])
{
char scelta[1];
char out[MAX_DIM];
char buff[MAX_DIM];
int ds_sock,/*ds_sock_acc,*/ret,lenght;
struct sockaddr_in server;
struct sockaddr client;
struct posto cinema[3][3];
//
inizializza_cinema(cinema);
//
system("clear" );
//qui ho omesso il codice del socket x snellire la lettura del testo

printf("in attesa di connessione da parte del client!!\n\n" );
//
//
while(1)
{
while((ds_sock_acc=accept(ds_sock,&client,&lenght)) ==-1);
printf("client connesso!!\n\n" );
if (fork()==0)
{ close(ds_sock);
do

{ strcpy(out," ");
read(ds_sock_acc,buff,MAX_DIM);
// scelta=buff;
if ((strcmp(buff,"A")==0)||(strcmp(buff,"a") ==0))
{ posti_vuoti(cinema);
//printf("%s\n",buff);
}
else if ((strcmp(buff,"B")==0)||(strcmp(buff,"b") ==0))
{
controllo_posto(cinema);
}

else if ((strcmp(buff,"C") ==0)||(strcmp(buff,"c") ==0))
{
annulla_posto(cinema);
}
else if((strcmp(buff,"D") ==0)||(strcmp(buff,"d") ==0))
{ strcpy(out,"fatto");
}

}//relativa al do
while (strcmp(out,"fatto") !=0);
//
write(ds_sock_acc,"\n\nArrivederci!!",20);
close(ds_sock_acc);
printf("Client disconnesso!!\n\n");
printf("\nIn attesa di connessione da nuovo client!!\n\n");
exit(0);

}//della fork
else close(ds_sock_acc); //è del fork==0

}//del while(1)
}//del main



La struttra posto l'ho definita cosi

struct posto
{
unsigned char idPosto[6];
int flag;
};

la funzione inizializza_cinema

void inizializza_cinema(struct posto cine[3][3])
{
unsigned char i,j,k;
k='1';
for(i='A';i<='C';i++)
{
//printf("\n");
for(j='1';j<='3';j++)
{
cine[i-'A'][j-'1'].flag=0;
cine[i-'A'][j-'1'].idPosto[0]=' ';
cine[i-'A'][j-'1'].idPosto[1]=i;
cine[i-'A'][j-'1'].idPosto[2]=j;
cine[i-'A'][j-'1'].idPosto[3]=' ';
cine[i-'A'][j-'1'].idPosto[4]='\t';
cine[i-'A'][j-'1'].idPosto[5]='\0';
}
cine[i-'A'][2].idPosto[4]='\n';
}


Non ben chiaro come procedere per risolvere. Se usare una matrice dinamica (ho il problema che la matrice l'ho dichiarata di tipo posto), memoria condivisa o tutte e due.
Spero che la discussione troppo lunga nn spaventi e che qualcuno riesca ad aiutarmi.

v1ruz
16-08-2005, 20:58
hai provato ad utilizzare un mutex per l'accesso al cinema?

viridovix1
17-08-2005, 12:26
il fatto è che la matirce è statica, x usare un mutex dovrei memorizzare la matrice statica su memoria condivisa, mumble... :confused:

Gica78R
17-08-2005, 14:24
Prescindendo dal codice che hai riportato (che non ho letto, so' troppo stanco... :cool: ), se vuoi che un client veda le modifiche apportate dagli altri credo tu abbia solo tre possibili soluzioni:

1) usare la memoria condivisa tra processi concorrenti, e quindi prevedere dei meccanismi di sincronizzazione tra i vari processi (semafori);
1-bis) usare la memoria condivisa e rinunciare alla concorrenza dei processi (gestendo un client per volta per evitare l'onere della sincronizzazione);
2) fare uso di altri sistemi di IPC (ad es. scambio di messaggi), cosa che pero' introdurrebbe il problema della gestione della coerenza dei dati.

viridovix1
18-08-2005, 10:56
[QUOTE=Gica78R]Prescindendo dal codice che hai riportato (che non ho letto, so' troppo stanco... :cool: ), se vuoi che un client veda le modifiche apportate dagli altri credo tu abbia solo tre possibili soluzioni:

1) usare la memoria condivisa tra processi concorrenti, e quindi prevedere dei meccanismi di sincronizzazione tra i vari processi (semafori);

Ecco appunto usare la memoria condivisa con un semaforo mutex.
Il server con il codice attuale accetta connessioni da piu' client contemporaneamnete (server concorrente) , e dovrebbe processare pero' le richieste di prenotazione sequenzialmente.
Il fatto è che nn so bene come modificare il codice x memorizzare la matrice in memoria condivisa. LA posso lasciare statica??
Penso che nel codice main del server debba creare la porzione di memoria condivisa e il semaforo(e settarlo), poi associarla nel codice che genera il figlio e sempre qui mettere le chiamate che blocchino e sblocchino il semaforo.
Dunque il problema rimane come spiattellare la matrice in memoria condivisa e poi passarla con la send o write ai client.
Con il codice attuale la matrice ripeto è statica e una volta nizializzata le varie prenotazioni sono memorizzate in un vettore idposto[6] in modo da passarle con la send.

la matrice l'ho definita cosi

struct posto
{ unsigned char idPosto[6];
int flag; // indica con 0 posto libero, con 1 prenotato
}

struct posto cinema[3][3];

ad ogni elemento della matrice è assegnato un vettore idPosto e un flag
Nel vettore quindi è memorizzato ad esempio

(spazio vuoto) 'A' 1' (spazio vuoto) (il tabulatore'\') '\0' vale x i posti liberi

'[' 'A' '1' ']' '\' '0' vale x posto prenotato chiuso tra parentesi

Gica78R
18-08-2005, 16:24
Per i semafori guarda qui: http://www.lilik.it/~mirko/gapil/gapilsu189.html#x498-24500012.2.5

mentre per la memoria condivisa, qui: http://www.lilik.it/~mirko/gapil/gapilsu190.html#x506-24600012.2.6

Sono link alla versione on-line di GaPiL, puoi scaricare anche la versione pdf; e' molto ben fatta :)

Ciao

viridovix1
19-08-2005, 09:39
TI ringrazio :) molto ben realizzata, pero' mi rimane il problema di come memorizzarci la matrice(statica) :(

Gica78R
23-08-2005, 16:22
TI ringrazio :) molto ben realizzata, pero' mi rimane il problema di come memorizzarci la matrice(statica) :(
Ehm... esattamente, cos'e' una matrice statica? :boh:
Dipende per caso dalla zona di memoria in cui e' allocata? Cioe' nello heap e non nello stack? Sinceramente non ho idea di dove venga allocato lo spazio per la memoria condivisa...

Ginogino
23-08-2005, 16:30
Sistema Suse 9.2, linguaggio C , compilatore gcc.
Ho realizzato un sistema di prenotazione posti per una sala cinematografica, con un processo su una macchina server che gestisce la mappa dei posti.
Ogni posto è caratterizzato da numero di fila, numero di poltrona e da un flag che indica se il posto è prenotato o meno.
Il server accetta e processa sequenzialmente le richieste prenotazioni di posti da uno o piu' client che possono essere sulla stessa macchina o in remoto(quindi macchine diverse).

Non ben chiaro come procedere per risolvere. Se usare una matrice dinamica (ho il problema che la matrice l'ho dichiarata di tipo posto), memoria condivisa o tutte e due.
Spero che la discussione troppo lunga nn spaventi e che qualcuno riesca ad aiutarmi.



Per curiosità, non è che a settembre dovrai affrontare un certo professor Quaglia? :asd:


BYeZzzZ

Gica78R
23-08-2005, 16:41
Per curiosità, non è che a settembre dovrai affrontare un certo professor Quaglia? :asd:


BYeZzzZ
Quaglia??? De "La Sapienza"??? Quando facevo il primo anno di ing. Informatica era l'assistente di Ciciani... Un giorno, all'inizio di giugno (ultime lezioni), Ciciani disse: "Quaglia questa settimana non c'e'!", e un mio amico, dalle retrovie, urlo': "E' periodo di migrazione: e' volato in un paese piu' freddo!" :D :rotfl:

RaouL_BennetH
23-08-2005, 17:09
Ehm... esattamente, cos'e' una matrice statica? :boh:
Dipende per caso dalla zona di memoria in cui e' allocata? Cioe' nello heap e non nello stack? Sinceramente non ho idea di dove venga allocato lo spazio per la memoria condivisa...

se quello che sto studiando su stack ed heap non è reso vano dalla mia ottusaggine,non dipende dalla zona di memoria in cui viene allocata se va a finire nello stack o nell'heap,ma dipende se è un "valore tipo" o se è "un valore riferimento".

Ginogino
24-08-2005, 09:30
Quaglia??? De "La Sapienza"??? Quando facevo il primo anno di ing. Informatica era l'assistente di Ciciani... Un giorno, all'inizio di giugno (ultime lezioni), Ciciani disse: "Quaglia questa settimana non c'e'!", e un mio amico, dalle retrovie, urlo': "E' periodo di migrazione: e' volato in un paese piu' freddo!" :D :rotfl:


Migrando migrando :fagiano: è diventato professore da un paio di anni o poco più, immagino.

Comunque è un bravo ragazzo. Un po flashato, ma gli ammmmmmolla ;)

BBella ingegnè!

Byezzz :cool:

Gica78R
24-08-2005, 10:12
BBella ingegnè!

Seeeeeeeeeeeee..... Magara! Sto ancora a carissimo amico :doh: :muro:

cdimauro
25-08-2005, 08:27
Per matrice statica, e in generale per dati statici, nel gergo s'intende non allocata dinamicamente: la struttura è "allocata" tutta in una volta in fase di caricamento dell'eseguibile.

Comunque la soluzione al problema secondo me è di definire una macchina che faccia da server, e che quindi memorizzi i dati in qualche modo, in modo che tutte le richieste di accesso ai dati vengano "centralizzate" (tramite delle API opportunamente definite).

Un'altra soluzione potrebbe essere quella di mettere su un server database condiviso da tutti i client. Quindi non esistono server, e tutte le applicazioni sono dei client. Il problema, in questo caso, è garantire la coerenza per quanto riguarda l'assegnazione dei posti, in modo da garantire che lo stesso posto venga prenotato da più persone.
La soluzione al problema è quella di usare un database che consenta di effettuare delle transazioni. Una transazione è una sequenza di operazioni (su un database in genere) che, una volta "chiusa", garantisce l'esecuzione di TUTTE le operazioni o di NESSUNA.
Mio consiglio personale è quello di usare un database come FireBird (open source / aggratis :D), che è molto solido e che permette non solo di gestire le transazioni, ma di scrivere procedure SQL che fanno tutto il lavoro. Ad esempio, è possibile scrivere una procedura "PrendiPosto", che si occupa di eseguire tutti i controlli e di assegnare il posto (o anche i posti): per i client è sufficiente chiamarla (come se fosse un comando SQL) e basta; pensa a tutto lei; e, grazie alle transazioni, se va in porto la chiamata si ha la garanzia che soltanto la nostra applicazione è riuscita a modificare QUEI particolari record "toccati" dall'operazione e nessun'altra.