Salve a tutti ragazzi , sto facendo un esercizio molto standard in cui ho un buffer con un solo campo e ho 5 processi produttori e 5 processi consumatori che si sincronizzano mediante un monitor di tipo signal and return : prima deve produrre un produttore , poi può consumare un consumatore e così via di seguito fino alla fine .
Io ho creato i file main.cpp,body.cpp,header.h,Makefile mentre quelli relativi al monitor mi sono stati già dati corretti e funzionanti. Il problema è che ottengo sempre l'errore "Errore di segmentazione (core dump creato)"
Il progetto prevede i seguenti file :
main.cpp :
[SPOILER][/SPOILER]codice:#include <iostream> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/wait.h> #include <sys/sem.h> #include <sys/shm.h> #include "monitor.h" #include "header.h" using namespace std; int main(){ //******PARTE DICHIARATIVA******* pid_t pid; key_t shmkey; int shmid; int stato; int num_proc,num_cons,num_prod; p_c_monitor* m; //******PARTE ESECUTIVA********** //inizializzo il numero di processi , di consumatori e di produttori num_cons = 5 ; num_prod = 5 ; num_proc = num_cons + num_prod; //inizializzo il monitor init_monitor( &(m->M), NUMCOND ); //inizializzo il valore della chiave della shm che ospiterà la struct p_c_monitor shmkey = IPC_PRIVATE; //genero tale shm shmid = shmget(shmkey, sizeof(p_c_monitor),IPC_CREAT|0664); //attacco la shm m = (p_c_monitor*) (shmat(shmid,0,0)); //inizializzo le variabili condition della mia struttura m->ok_prod=1; m->ok_cons=0; //genero num_proc processi figli , metà produttori e metà consumatori for(int i=0; i < num_proc ; i++){ if(pid==0){ if( (i%2)==0 ){ //Processo Conumatore cout<<"sono il processo consumatore numero: "<<getpid()<<endl; sleep(1); consumazione(m); } else{ //Processo Produttore cout<<"sono il processo produttore numero: "<<getpid()<<endl; sleep(1); produzione(m); } exit(0); } } //attendo la terminazione dei figli for(int i=0; i < num_proc ; i++){ pid = wait(&stato); if(pid==-1) cout<<"Errore\n"; else cout<<"Il figlio numero: "<<pid<<" è terminato con stato: "<<stato<<endl; } //Rimuovo le strutture shmctl(shmid,IPC_RMID,0); remove_monitor( &(m->M) ); return 0; }
header.h
[SPOILER][/SPOILER]codice:/*Si vuole realizzare il classico problema produttore consumatore con un unico buffer attraverso un'applicazione multiprocesso dove n processi sono produttori ed m processi sono consumatori e si vuole usare il costrutto monitor implementato come signal_and_return*/ //Definisco IL NUMERO delle variabili condition che mi servirà per la monitor_init e gli id che voglio usare per essi #define NUMCOND 2 #define OK_PROD 0 #define OK_CONS 1 //definisco il monitor includendovi anche il buffer e l'implementazione di monitor già fatta e definisco il tipo di messaggio typedef long msg; typedef struct{ //variabili condition: int ok_prod; int ok_cons; //buffer: msg messaggio; //monitor da usare già implementato: Monitor M; } p_c_monitor; //definisco le funzioni void produzione(p_c_monitor*); void inizio_produzione(p_c_monitor*); void fine_produzione(p_c_monitor*); void consumazione(p_c_monitor*); void inizio_consumazione(p_c_monitor*); void fine_consumazione(p_c_monitor*);
body.cpp
[SPOILER][/SPOILER]codice:#include <iostream> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/wait.h> #include <sys/sem.h> #include <sys/shm.h> #include "monitor.h" #include "header.h" #include <sys/time.h> using namespace std; void produzione(p_c_monitor* m){ inizio_produzione(m); struct timeval t1; struct timezone t2; gettimeofday(&t1,&t2); m->messaggio = t1.tv_usec; cout<<"Valore prodotto : "<<m->messaggio<<endl; fine_produzione(m); } void inizio_produzione(p_c_monitor* m){ enter_monitor(&(m->M)); if( !(m->ok_prod) ) //se ok_prod non è verificata , è falsa , quindi non posso produrre, mi devo sospendere su questa condizione wait_condition(&(m->M),OK_PROD); } void fine_produzione(p_c_monitor* m){ //aggiorno i valori delle variabili logiche stabilendo che il buffer è pieno e non si può più produrre ma si può consumare m->ok_prod = 0; m->ok_cons = 1; //faccio una signal per sbloccare i consumatori in coda signal_condition( &(m->M),OK_CONS); //esco dal monitor leave_monitor(&(m->M)); } void consumazione(p_c_monitor* m){ inizio_consumazione(m); cout<<"Il messaggio consumato è: "<<m->messaggio<<endl; fine_consumazione(m); } void inizio_consumazione(p_c_monitor* m){ enter_monitor(&(m->M)); if(!(m->ok_cons)) wait_condition( &(m->M),OK_CONS); } void fine_consumazione(p_c_monitor* m){ m->ok_prod = 1; m->ok_cons = 0; signal_condition( &(m->M) , OK_PROD); leave_monitor(&(m->M)); }
monitor.h
[SPOILER][/SPOILER]codice:/***PROTOTIPI DELLE PROCEDURE PER LA REALIZZAZIONE DEL COSTRUTTO MONITOR***/ typedef struct { int mutex; int num_var_cond; //id del gruppo sem associati alle var.cond int id_conds; //array delle variabili condition_count int *cond_counts; //identificativo memoria condivisa int id_shared; } Monitor; //monitor e numero di variabili condition void init_monitor (Monitor*, int); void enter_monitor(Monitor*); void leave_monitor(Monitor*); void remove_monitor(Monitor*); void wait_condition(Monitor*,int); void signal_condition(Monitor*,int);
monitor.cpp
[SPOILER][/SPOILER]codice:/*************************************Monitor*************************************************/ // Implementazione di un Monitor #include <sys/ipc.h> #include <sys/types.h> #include <sys/sem.h> #include <sys/shm.h> #include <stdio.h> #include <unistd.h> #include "monitor.h" //Funzioni di utilita' private alla libreria Monitor static void Wait_Sem(int, int); static void Signal_Sem (int,int); static int Queue_Sem (int,int); //restituisce il num di processi in attesa su un semaforo /********************IMPLEMENTAZIONE DELLE PROCEDURE***********************/ void init_monitor (Monitor *M,int num_var){ int i; M->num_var_cond=num_var; M->mutex=semget(IPC_PRIVATE,1,IPC_CREAT|0664); M->id_conds=semget(IPC_PRIVATE,num_var,IPC_CREAT|0664); semctl(M->mutex,0,SETVAL,1); for (i=0;i<num_var;i++) semctl(M->id_conds,i,SETVAL,0); M->id_shared=shmget(IPC_PRIVATE,num_var*sizeof(int),IPC_CREAT|0664); M->cond_counts=(int*) (shmat(M->id_shared,0,0)); for (i=0;i<num_var;i++) M->cond_counts[i]=0; #ifdef DEBUG_ printf("Monitor inizializzato con %d condition variables. Buona Fortuna ! \n",num_var); #endif } void enter_monitor(Monitor * M){ #ifdef DEBUG_ printf("<%d> Tentativo di ingresso nel monitor... \t",getpid() ); #endif Wait_Sem(M->mutex,0); #ifdef DEBUG_ printf("<%d> Entrato nel monitor \n",getpid() ); #endif } void leave_monitor(Monitor* M){ #ifdef DEBUG_ printf("<%d> Uscito dal monitor \n", getpid()); #endif Signal_Sem(M->mutex,0); } void remove_monitor(Monitor* M){ semctl(M->mutex,0,IPC_RMID,0); semctl(M->id_conds,M->num_var_cond,IPC_RMID,0); shmctl(M->id_shared,IPC_RMID,0); #ifdef DEBUG_ printf(" \n Il Monitor è stato rimosso ! Arrivederci \n", getpid()); #endif } void wait_condition(Monitor* M,int id_var){ #ifdef DEBUG_ printf("<%d> -Monitor- invocata la wait sulla condition numero %d\n", getpid(), id_var); #endif M->cond_counts[id_var]=M->cond_counts[id_var]+1; Signal_Sem(M->mutex,0); Wait_Sem(M->id_conds,id_var); M->cond_counts[id_var]=M->cond_counts[id_var]-1; } void signal_condition(Monitor* M,int id_var){ #ifdef DEBUG_ printf("<%d> -Monitor- tentativo di signal; n.ro proc. in attesa sulla cond. n. %d = %d\n", getpid(), id_var,M->cond_counts[id_var]); #endif if(M->cond_counts[id_var]>0) { Signal_Sem(M->id_conds,id_var); #ifdef DEBUG_ printf("<%d> -Monitor- invocata la signal sulla condition numero %d\n", getpid(), id_var); #endif } else { Signal_Sem(M->mutex,0); #ifdef DEBUG_ printf("<%d> -Monitor- invocata la signal sul mutex \n", getpid()); #endif } } /********************IMPLEMENTAZIONE DELLE PROCEDURE SEMAFORICHE***********************/ void Wait_Sem(int id_sem, int numsem) { struct sembuf sem_buf; sem_buf.sem_num=numsem; sem_buf.sem_flg=0; sem_buf.sem_op=-1; semop(id_sem,&sem_buf,1); //semaforo rosso } // restituisce il numero di processi in attesa sul semaforo int Queue_Sem(int id_sem, int numsem) { return (semctl(id_sem,numsem,GETNCNT,NULL)); } void Signal_Sem (int id_sem,int numsem) { struct sembuf sem_buf; sem_buf.sem_num=numsem; sem_buf.sem_flg=0; sem_buf.sem_op=1; semop(id_sem,&sem_buf,1); //semaforo verde }
Makefile
[SPOILER][/SPOILER]codice:start: main.o body.o monitor.o g++ -o start main.o body.o monitor.o main.o: main.cpp header.h g++ -c main.cpp body.o: body.cpp header.h g++ -c body.cpp monitor.o: monitor.h monitor.cpp g++ -c monitor.cpp clean: rm -f *.o rm -f ./start rm -f *~
Ho già individuato la parte critica , ossia :
in main.cpp, infatti commentando quell'unica riga di codice , non ricevo più l'errore " Errore di segmentazione (core dump creato) " ,codice:init_monitor( &(m->M), NUMCOND );
Grazie mille in anticipo a chiunque possa aiutarmi.

Rispondi quotando