Comunque dopo un pò di sbattimenti sono riuscito a trovare una soluzione funzionante, anche se ho dovuto semplificare il programma, togliendo le struct e considerando la memoria condivisa come un grande vettore ad int !
Comunque se qualcuno mi dà qualche suggerimento ad implementarla anche con le struct si potrebbe provare a farla, il dubbio che mi resta è sempre lo stesso, volendo utilizzare la prima cella di memoria come un contatore e quindi una locazione ad int si possono utilizzare le altre locazioni con altri tipi di dati, come ad esempio delle struct?
Perchè se utilizziamo un puntatore alla memoria questo potrà essere solo di un determinato tipo, quindi se lo dichiariamo ad interi
"int *shmPtr " per utilizzare la prima locazione come contatore, non possiamo utilizzarlo per passare delle struct, allora mi chiedevo si possono dichiarare più puntatori alla memoria? Quindi magari potremmo farne uno ad interi per usarlo come contatore e crearne un altro di tipo struct! Che mi dite?
Vi posto il programma funzionante senza struct, al quale mi riferivo sopra, magari a qualcuno può sempre far comodo!
SERVER
codice:
/*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.*/
#include <stdio.h>
#include <stdlib.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 SHMSIZE 1000
#define SIZE 32 // l'array deve immagazinare dati per tutti i 31 giorni di agosto
// non usiamo la locazione 0
void alrm(int s);
int i, done, count, data, semid, shmid;
int *shmPtr; // puntatore alla memoria
//--------- MAIN --------------------------------------------------------------------------------------------------------
int main() {
count = 0;
done = 1;
key_t mykey1 = 1234; // chiave del semaforo
key_t mykey2 = 4321; // chiave della memoria
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
semid=semget(mykey1,1,IPC_CREAT|IPC_EXCL|0666); // creiamo il semaforo
semctl(semid,0,SETVAL,1); // settiamo il primo semaforino ad 1, la risorsa è presa da arg.val
shmid= shmget(mykey2, SHMSIZE, IPC_CREAT|0600); // creiamo la memoria condivisa
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
shmPtr[0] = 0; // inizializiamo a 0 la prima cella di memoria, la useremo come contatore dei client
shmdt(shmPtr);
semop(semid,&sem_unlock,1);
signal(SIGALRM,alrm); // signal cattura SIGALARM e la lancia la funzione alrm
alarm(20); // il server resterà attivo per un ora 3600
while(done==1){
sleep(1);
} // contiamo i client che hanno scritto nella memoria
printf("Il tempo per l'inserimento è scaduto\n");
semop(semid, &sem_lock,1);
shmPtr=shmat(shmid,0,SHM_RDONLY);
count = shmPtr[0]; // in count il n° di client che hanno scritto in memoria (n° nella prima locazione della mem)
printf("Ci sono state %d richieste\n", count);
for(i=1;i<SIZE;i++){ // rispetta i vincoli, ogni giorno possono prenotarsi
if(shmPtr[i]>50 && shmPtr[i]<250) // min 50 persone e max 250
printf("Per il giorno %d la prenotazione è stata accettata! Si sono prenotate %d persone\n", i, shmPtr[i]);
else
printf("Per il giorno %d la prenotazione non è stata accettata! Si sono prenotate %d persone\n", i, shmPtr[i]);
}
shmdt(shmPtr);
semop(semid,&sem_unlock,1);
semctl(semid,0,IPC_RMID,0);
shmctl(shmid,IPC_RMID,NULL);
exit(0);
}
void alrm(int s) {
done=0;
}
CLIENT
codice:
#include <stdio.h>
#include <stdlib.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 SHMSIZE 1000
#define SIZE 32 // l'array deve immagazinare dati per tutti i 31 giorni di agosto
// non usiamo la locazione 0
int i, j, count, pid, semid, shmid;
struct sembuf sem_lock={0,-1,0}; // lock del semaforo
struct sembuf sem_unlock={0,1,0}; // unlock del semaforo
int *shmPtr; // puntatore alla memoria
int main(int argc, char* argv[]){
key_t mykey1 = 1234; // chiave del semaforo
key_t mykey2 = 4321; // chiave della memoria
char cognome[20];
int data, n_persone;
// ---- 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(j=1;j<argc;j++){ // il primo argomento argv[0] è prenotazione, il nome del software Client
strcpy(cognome,argv[1]);
data = atoi(argv[2]); // il terzo argomento è la data in cui si vuole prenotare la vacanza
n_persone = atoi(argv[3]);//il quarto argomento è il numero di persone per il quale si vuole prenot
}
printf("In data %d agosto il signor %s ",data,cognome);
printf("ha prenotato per %d persone\n",n_persone);
// ---- Fine Riempimento struttura --------------------------------------------------------------------------------------
semid=semget(mykey1, 0, 0666); // ci agganciamo al semaforo
shmid=shmget(mykey2, 0, 0); // ci attacchiamo alla memoria condivisa
if(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
shmPtr[0] = shmPtr[0]+1; // incrementiamo il contatore della prima locazione //*shmPtr= *shmPtr+1;
count = shmPtr[0];
shmPtr[data] = shmPtr[data] + n_persone; // aggiorniamo per ogni data il numero di persone che vogliono prenotarsi
//printf("Hanno scritto in memoria %d client\n", count);
shmdt(shmPtr);
semop(semid,&sem_unlock,1);
}
else
printf("Possono partecipare solo nuclei familiari composti da almeno 2 persone\n");
exit(0);
}