Visualizzazione dei risultati da 1 a 3 su 3
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    505

    C - thread e memoria condivisa - comportamento strano

    salve, stò realizzando una mini applicazione (a scopo didattico diciamo) composta da due aree di scrittura lettura critiche(gestite con mutex e condition variables) e 3 thread che operano su di esse; primo thread genera delle stringhe a caso e le invia al thread 2 (tramite il "buffer" circolare port p). il thread 2 riceve, elabora e le invia al thread 3 (tramite il "buffer" circolare port q).

    questo il codice :
    codice:
    #include <pthread.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <time.h>
    
    #define N 1
    
    // definisco una struttura messaggio che mi servirà per la lettura/scrittura delle stringhe
    struct msg {
    	char *mex;
    };
    
    // definisco struttura port; area array circolare con relativi parametri come vettore di N elementi di tipo msg, mutex e condition variables (regione critica, operazioni atomiche)
    struct port {
    	struct msg messages[N];
    	pthread_mutex_t m;
    	pthread_cond_t empty;
    	pthread_cond_t full;
    	int count;
    	int head;
    	int tail;
    };
    
    // inizializzo struttura port
    struct port *port_init(void) {
    	struct port *p;
    
    	p = malloc(sizeof(struct port));
    	if (p == NULL) {
    		return NULL;
    	}
    
    	p->head = 0;
    	p->tail = 0;
    	p->count = 0;
    	pthread_mutex_init(&p->m, NULL);
    	pthread_cond_init(&p->empty, NULL);
    	pthread_cond_init(&p->full, NULL);
    
    	return p;
    }
    
    // definisco puntatore struttura port (variabili visibili da tutto il processo (quindi condivise tra i singoli thread)
    struct port *p, *q;
    int passo=1;
    
    void msg_send(struct port *p, struct msg *m) {
    	// accedo in mutua esclusione
    	pthread_mutex_lock(&p->m);
    	while (p->count == N) {
    		// controlla (ciclicamente) la condition variable. se la coda è piena sblocca il mutex (per gli altri processi) e si blocca; altrimenti blocca il mutex e scrive
    		pthread_cond_wait(&p->full, &p->m);
    	}
      
    	// scrivo il messaggio nell'area condivisa
    	memcpy(&p->messages[p->tail], m, sizeof(struct msg));
    	
    	// incremento la coda e il count
    	p->tail = (p->tail + 1) % N;
    	p->count = p->count + 1;
    	
    	// dormo per un pò (per far notare l'invio)
    	usleep(500000);		
    	
    	// sblocco condition variable e il mutex
    	pthread_cond_signal(&p->empty);
    	pthread_mutex_unlock(&p->m);
    }
    
    void msg_receive(struct port *p, struct msg *m) {
    	// accedo in mutua esclusione
    	pthread_mutex_lock(&p->m);
    	while (p->count == 0) {
    		// controlla (ciclicamente) la condition variable. se la coda è vuota sblocca il mutex (per gli altri processi) e si blocca; altrimenti blocca il mutex e legge
    		pthread_cond_wait(&p->empty, &p->m);
    	}
      	
    	// leggo il messaggio nell'area condivisa
    	memcpy(m, &p->messages[p->head], sizeof(struct msg));
    	
    	// decremento testa e count
    	p->head = (p->head + 1) % N;
    	p->count = p->count - 1;
    	
    	// dormo per un pò (per far notare la ricezione)
    	usleep(500000);		
    	
    	// sblocco condition variable e il mutex
    	pthread_cond_signal(&p->full);
    	pthread_mutex_unlock(&p->m);
    }
    
    void *th1_create(void *v) {
    	// definisco la mia struttura messaggio, stringa da generare e attributi per questo thread
    	struct msg m;
    	char str_random[10];
    	int j,i, cs=0;
    		
    	srand(time(NULL));
    	// genero e invio 10 stringhe
    	for (i=0; i<10; i++) {
    		for (j=0; j<10; j++) {
    			str_random[j]=rand() % 93 + 33;
    		}		
    		m.mex=str_random;		
    		
    		msg_send(p, &m);
    		cs++;
    		printf("%d - T1 - Stringa n.%d inviata : %s\n", passo++, cs, m.mex);		
    	}		
    
    	// invio messaggio chiusura da parte del thread 1
    	m.mex="end_transmission_t1";
    	msg_send(p, &m);
    
    	return NULL;
    }
    
    void *th2_elabore(void *v)  {
    	// definisco la mia struttura messaggio, stringa da generare e attributi per questo thread
    	struct msg m;
    	char str_conv[20];
    	int i=1, cs=0;
    	
    	// ricevo, elaboro e invio le 10 stringhe
    	while(i==1) {
    		msg_receive(p, &m);	
    		if(m.mex=="end_transmission_t1") {
    			i=2;
    		} else {
    			int j, count_pwd=0;
    			for (j=0; j<10; j++) {
    				count_pwd=count_pwd+(int)m.mex[j];
    			}
    
    			sprintf(str_conv, "%s%d", "", count_pwd);
    			
    			cs++;
    			printf("%d - T2 - Stringa n.%d ricevuta : %s - Codifica corrispondente : %d\n", passo++, cs, m.mex, count_pwd);
    					
    			m.mex=str_conv;
    			msg_send(q, &m);
    		}
    	}	
    
    	// invio messaggio chiusura da parte del thread 2
    	m.mex="end_transmission_t2";
    	msg_send(q, &m);
    
    	return NULL;
    }
    
    void *th3_send(void *v) {
    	// definisco la mia struttura messaggio, stringa da generare e attributi per questo thread
    	struct msg m;
    	int i=1, cs=0;
    	
    	// ricevo e invio al device driver le mie 10 stringhe
    	while(i==1) {
    		msg_receive(q, &m);	
    		if(m.mex=="end_transmission_t2") {
    			i=2;
    		} else {
    			int j, count_pwd=0;
    			for (j=0; j<10; j++) {
    				count_pwd=count_pwd+(int)m.mex[j];
    			}
    			cs++;
    			printf("%d - T3 - Stringa n.%d elaborata ricevuta : %s\n", passo++, cs, m.mex);
    		}
    	}	
    
    	return NULL;
    }
    
    int main(int argc, char *argv[]) {
    	int err;
    	pthread_t th1, th2, th3;
    
    	p = port_init();
    	q = port_init();
      err = pthread_create(&th1, NULL, th1_create, NULL);
      if (err) {
        perror("PThread Create");
      }
    
      err = pthread_create(&th2, NULL, th2_elabore, NULL);
      if (err) {
        perror("PThread Create");
      }
    
      err = pthread_create(&th3, NULL, th3_send, NULL);
      if (err) {
        perror("PThread Create");
      }
    
      pthread_join(th1, NULL);
      pthread_join(th2, NULL);
      pthread_join(th3, NULL);
    
      printf("\nStrings sent successfully...\n");
    
      return 0;
    }
    il problema stà nel fatto che T1 invia, T2 riceve ma riceve la stringa che T1 (in teoria) dovrebbe inviare al secondo passo... non capisco se è un problema di casting o che cosa...

    infatti, nel th1_create se sostituisco :
    codice:
    		for (j=0; j<10; j++) {
    			str_random[j]=rand() % 93 + 33;
    		}
                    m.mex=str_random;
    con :

    codice:
    		if(i==0) m.mex="aaaaaaaaa0";
    		if(i==1) m.mex="aaaaaaaaa1";
    		if(i==2) m.mex="aaaaaaaaa2";
    		if(i==3) m.mex="aaaaaaaaa3";
    		if(i==4) m.mex="aaaaaaaaa4";
    		if(i==5) m.mex="aaaaaaaaa5";
    		if(i==6) m.mex="aaaaaaaaa6";
    		if(i==7) m.mex="aaaaaaaaa7";
    		if(i==8) m.mex="aaaaaaaaa8";
    		if(i==9) m.mex="aaaaaaaaa9";
    funziona tutto alla perfezione...

    aspetto delucidazioni perchè non riesco a capire!

    cordiali saluti

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Non ho esaminato in dettaglio tutto il codice ma si tratta probabilmente di un problema di sincronizzazione. Se provi a mettere una sleep() (ad esempio, sleep(2)) in th1_create() dopo la msg_send(), il tuo programma dovrebbe funzionare correttamente. Evidentemente una volta inviato il messaggio, prima che l'altro thread riesca a leggere la stringa, il thread che genera le stringhe arriva già a modificare il puntatore m.mex, cambiando la stringa in questione con quella successiva. Ti consiglio comunque di modificare qualcosa nella stessa funzione:

    codice:
           char str_random[11];
    
    
    	for (j=0; j<10; j++) {
    		str_random[j]=rand() % 93 + 33;
    	}
    
            str_random[j] = '\0';
    every day above ground is a good one

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2008
    Messaggi
    505
    yeah...era il puntatore alla struttura, non problemi di thread. ho risolto con :

    codice:
           struct mst {
             char mex[10];
           }
    yeah grazie comunque per la risposta!!!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.