Ciao a tutti, sto cercando di imparare l'utilizzo della memoria condivisa regolata da semafori!
Ora vi posto il mio programma, c'è un codice per il server ed uno per il client, la compilazione va a buon fine, ma c'è qualche errore logico poichè nell'esecuzione ho un "Segmentation fault"!
In particolare ho qualche dubbio e difficoltà riguardo l'utilizzo dei puntatori nella memoria, infatti ho bisogno di azzerare la prima cella di memoria per utilizzarla come contatore, e farla incrementare dai client che scriveranno in memoria, ma per creare un contatore, ho bisogno di un puntatore di tipo int, mentre per scrivere nelle altre locazioni di memoria ho bisogno di un puntatore di tipo struct, posso scrivere nella memoria dati di tipo diverso? E se si come faccio poi per l'attach della memoria, perchè se uso per l'attach un puntatore di tipo struct, poi non posso accedere alla prima locazione che dovrebbe essere di interi, d'altronde non posso azzerare una locazione di tipo struct! Quindi come faccio?
Altra domandina, ho provato a cercare su internet un pò di materiale e ho visto che nell'operazione di attach
"shmPtr=(struct prenotazione*)shmat(shmid,0,0);" ,da qualche parte facevano il cast per assegnare al puntarore l'indirizzo della memoria altre fonti invece non lo facevano, tipo: "shmPtr=shmat(shmid,0,0);" , perchè?
Illuminatemi, please! :'(
P.S. Di sicuro manca qualcosa, il programma è incompleto, in modo particolare il client, ma mi sono fermato cercando di capire l'errore "Segmentation fault" in fase di esecuzione e quindi cercando di sciogliere quei dubbi sull'utilizzo del contatore nella memoria!
/*La compagnia aerea Sky Airline ha pensato di offrire ai clienti dell’agenzia di viaggi Volare
di Napoli per il mese di agosto una offerta eccezionale sull’unico volo giornaliero da Napoli a
Barcellona. Le condizioni dell’offerta sono le seguenti:
• possono partecipare solo nuclei familiari composti da almeno 2 persone;
• l’offerta sarà valida solo se per il giorno scelto ci sono almeno 50 e al più 250 prenotazioni;
• le prenotazioni devono avvenire solo il giorno 10 luglio dalle 11:00 alle 12:00, presso l’agenzia Volare;
• i clienti avranno conferma o meno immediatamente dopo le 12:00 del 10 luglio.
La compagnia aerea ha allora fornito alla agenzia Volare un software Server, di nome Offerta,
ed un software Client, di nome Prenotazione, tale che se la famiglia Rossi, composta da 4
persone, è interessata all’offerta per il giorno 25 agosto, potrà digitare sul computer messo a disposizione dall’agenzia Prenotazione Rossi 25 4
Scrivere in linguaggio C il codice per il processo Server Offerta e per il generico processo client
Prenotazione: il processo Server deve controllare per ciascuno dei giorni del mese di agosto
che il numero di prenotazioni rientri nei limiti stabiliti. I client hanno 1 ora di tempo per
inserire. Il processo Server deve comunicare l’esito dell’offerta per ciascuno dei giorni del mese
di agosto.
- Implementare il precedente scenario ipotizzando che la comunicazione da client
a server avvenga attraverso la memoria condivisa il cui accesso sia regolato da un semaforo.
Il server comunica l’esito dell’offerta alla scadenza dell’ora scrivendolo sullo standard output: per
ciascuno dei giorni di agosto comunica solo se tutte le prenotazioni fatte sono accettate o no.*/
SERVER
CLIENTcodice:#include <stdio.h> #include <unistd.h> #include <sys/types.h> // utilizzate per i semafori e shm #include <sys/ipc.h> // utilizzate per i semafori e shm #include <sys/sem.h> // utilizzate per i semafori #include <sys/shm.h> // utilizzata per la shm #include <sys/stat.h> #include <fcntl.h> #include <signal.h> # include <string.h> #define SIZE 32 // l'array deve immagazinare dati per tutti i 31 giorni di agosto // non usiamo la locazione 0 #define SHMSIZE 1000 void alrm(int s); int i, done, count, data, semid, shmid; struct prenotazione{ char cognome[20]; int data; int n_persone; int pid; }pren; // variabile di tipo struct prenotazione int *countPtr; struct prenotazione *shmPtr; // puntatore di tipo struct prenotazione int giorno[SIZE]; // nell'array giorno[] immagaziniamo il numero di persone prenotate giorno per giorno int main() { int count = 0; int done = 1; key_t mykey1 = 1234; // chiave del semaforo key_t mykey2 = 4321; // chiave della memoria for(i=0;i<=SIZE;i++){ // azzeriamo il vettore giorno[i]=0; } union semun{ // struttura utilizzata da semctl con SETVAL per settare il valore del semaforino int val; // a 1, infatti alla variabile val sarà assegnato il valore 1 } arg; arg.val=1; // il valore sem_lock viene sottratto al valore del semaforino (valore del semaforino nella struttura sem) struct sembuf sem_lock={0,-1,0}; // lock del semaforo di 1 risorsa sul primo semaforino // il valore sem_unlock viene sommato al valore del semaforino (valore del semaforino nella struttura sem) struct sembuf sem_unlock={0,1,0}; // unlock del semaforo // creiamo il semaforo semid=semget(mykey1,1,IPC_CREAT|IPC_EXCL|0666); semctl(semid,0,SETVAL,1); // settiamo il primo semaforino ad 1, la risorsa è presa da arg.val // inizializiamo a 0 la prima cella di memoria, la utilizzeremo come contatore dei client shmid= shmget(mykey2, SHMSIZE, IPC_CREAT|0600); // creiamo la memoria condivisa semop(semid, &sem_lock, 1); // lockiamo 1 unità di risorsa shmPtr=(struct prenotazione*)shmat(shmid,0,0); // lo 0 al 2° parametro, indica che attacca il segmento dove possibile *countPtr=0; // nello spazio dati del processo shmdt(shmPtr); semop(semid,&sem_unlock,1); signal(SIGALRM,alrm); // signal cattura SIGALARM e la lancia la funzione alrm alarm(30); // il server resterà attivo per un ora 3600, ( vabbè facciamo 30s ) solo per verificare il funzionamento while(done==0){ // contiamo i client che hanno scritto nella memoria printf("Il tempo per l'inserimento è scaduto\n"); printf("Hanno scritto nella memoria %d client", count); semop(semid, &sem_lock,1); shmPtr=shmat(shmid,0,SHM_RDONLY); count = *countPtr; for(i= 1; i <= count; i++ ){ // un for dalla loazione 1 fino al n° di client che hanno scritto data = pren.data; printf("in data %d agosto il signor %s ha prenotato per %d persone\n",pren.data,pren.cognome,pren.n_persone); giorno[pren.data] = giorno[pren.data] + pren.n_persone; // la data della prenotazione sarà l'indice dell'array giorno, ad ogni locazione avremo la somma // delle persone prenotate per quel giorno } shmdt(shmPtr); semop(semid,&sem_unlock,1); } for(i=1;i<SIZE;i++){ // rispetta i vincoli, ogni giorno possono prenotarsi if(giorno[i]>50 && giorno[i]<250) // min 50 persone e max 250 printf("Per il giorno %d la prenotazione è stata accettata! :) \n", i); else printf("Per il giorno %d la prenotazione non è stata accettata!\n", i); sleep(1); semctl(semid,0,IPC_RMID,0); shmctl(shmid,IPC_RMID,NULL); if(( kill(pren.pid,SIGKILL) )==-1) printf("Impossibile uccidere il processo client %d\n", pren.pid); } } void alrm(int s) { done=0; }
codice:#include <stdio.h> #include <unistd.h> #include <sys/types.h> // utilizzate per i semafori e shm #include <sys/ipc.h> // utilizzate per i semafori e shm #include <sys/sem.h> // utilizzate per i semafori #include <sys/shm.h> // utilizzata per la shm #include <sys/stat.h> #include <fcntl.h> #include <signal.h> # include <string.h> #define SIZE 32 // l'array deve immagazinare dati per tutti i 31 giorni di agosto // non usiamo la locazione 0 #define SHMSIZE 1000 int i, done, data, semid, shmid; struct sembuf sem_lock={0,-1,0}; // lock del semaforo struct sembuf sem_unlock={0,1,0}; // unlock del semaforo struct prenotazione{ char cognome[20]; int data; int n_persone; int pid; }; // variabile di tipo struct prenotazione int *countPtr; struct prenotazione *shmPtr; // puntatore di tipo struct prenotazione int main(int argc, char* argv[]){ key_t mykey1 = 1234; // chiave del semaforo key_t mykey2 = 4321; // chiave della memoria struct prenotazione pren; struct prenotazione *shmPtr; // puntatore di tipo struct prenotazione shmPtr = &pren; // facciamo puntare la variabile struttura a shmPtr // ---- Inizio Riempimento struttura ----------------------------------------------------------------------------------- if(argc!=4){ // verifichiamo se gli argomenti passati da linea di comando sono 3 printf("Numero di argomenti errato!\n"); printf("Digitare: prenotazione cognome data n_persone\n"); } for(i=1;i<argc;i++){ // il primo argomento argv[0] è prenotazione, il nome del software Client strcpy(pren.cognome,argv[1]); pren.data = atoi(argv[2]); // il terzo argomento è la data in cui si vuole prenotare la vacanza pren.n_persone = atoi(argv[3]);//il quarto argomento è il numero di persone per il quale si vuole prenot } pren.pid=getpid(); // mettiamo nella struct il pid del client // ---- Fine Riempimento struttura -------------------------------------------------------------------------------------- if(pren.n_persone>1){ semop(semid, &sem_lock, 1); // lockiamo 1 unità di risorsa shmPtr=shmat(shmid,0,0); // lo 0 al 2° parametro, indica che attacca il segmento dove possibile *countPtr++ ; // verra sommata alla locazione 0 della memoria +1, ciò per incrementare il contatore *shmPtr = pren; // scriviamo la struttura al primo indirizzo disponibile shmdt(shmPtr); semop(semid,&sem_unlock,1); } else printf("Possono partecipare solo nuclei familiari composti da almeno 2 persone\n"); while(1); }

Rispondi quotando