Pipe e segnali

di il
4 risposte

Pipe e segnali

Ciao! Devo scrivere il seguente programma in c utilizzando pipe e segnali: il main genera due processi fratelli, ognugno dei due processi figli legge un file di interi in ingresso e conta il numero di occorrenze di un intero (gli interi che devono contare i due processi sono diversi). Il main legge le occorrenze, invia un segnale di vittoria al processo che ha contato più occorrenze e uno di sconfitta a quello che ne ha contate meno. In caso di pareggio è il main che scrive. I processi comunicano tramite pipe.
Il file e i due interi da contare sono inviati da riga di comando.
Scrivo qui il codice:
#include <stdio.h>
  #include <stdlib.h>
  #include <fcntl.h>
  #include <signal.h>
  #include <sys/wait.h>
  #include <string.h>

  #define READ 0
  #define WRITE 1
	
char* nomefile;	
int p1p0[2], p2p0[2];	// pipe

void vittoria(int signo) {
	printf("Ho vinto: %d\n", getpid());
}

void sconfitta(int signo) {
	printf("Ho perso: %d\n", getpid());
}
	
int numero_occorrenze(int valore, int elementi);
	

  int main(int argc, char *argv[])
  {
	FILE* fp;
	int dim;
	int occorrenze1, occorrenze2;
	int valore1, valore2;
	int num;
	int result1, result2;	
	int p1,p2;		// pid processi figli
	pipe(p1p0);	// pipe tra processo padre e figlio
	pipe(p2p0);

	if(argc!=4) {
		printf("Numero parametri errato\n");
		return -1;
	}

	nomefile=argv[1];	// 1° argomento: nome del file 
	valore1=atoi(argv[2]);	// 2° argomento: valore1 da cercare
	valore2=atoi(argv[3]);	// 3° argomento: valore2 da cercare

	// calcolo dimensione file
	fp=fopen(nomefile, "r");
	fseek(fp,0,SEEK_END);		// posizionamento alla fine del file
	dim=ftell(fp);			// dimensione del file in byte
	num=dim/sizeof(int);		// numero di interi
	
	printf("La dimensione del file e' %d bytes\n", dim);
	printf("Il numero di interi e' %d\n", num);

	p1=fork();
	if(p1==0) {
		printf("Sono il figlio 1 con pid %d\n", getpid());
		occorrenze1=numero_occorrenze1(valore1,dim);
		exit(0);	
	}
	
	p2=fork();
	if(p2==0) {
		printf("Sono il figlio 2 con pid %d\n", getpid());
		occorrenze2=numero_occorrenze2(valore2,dim);
		exit(0);	
	}	
	
	read(p1p0[READ], &result1, sizeof(int));
	printf("Il numero di occorrenze di %d e' %d\n", valore1, result1);
	read(p2p0[READ], &result2, sizeof(int));
	printf("Il numero di occorrenze di %d e' %d\n", valore2, result2);
	
	if(result1 > result2) {
		kill(p1,SIGUSR1);
		kill(p2,SIGUSR2);
	} else if(result2 > result1) {
		kill(p1,SIGUSR2);
		kill(p2,SIGUSR1);
	} else if(result1 == result2)
		printf("Pareggio!\n");
		

	fclose(fp);
	
	wait(NULL);
	wait(NULL);
	
	return 0;
  }


int numero_occorrenze1(int valore, int elementi) {
		FILE* f;
		int i, s;
		int occorrenze=0;
		f=fopen(nomefile, "rb");
		close(p1p0[READ]);
		fseek(f,0,SEEK_SET);
		for(i=0;i<elementi;i++) {
			fread(&s,sizeof(int),1,f);
			if(s==valore) {
				occorrenze++;
			}
		}
		write(p1p0[WRITE], &occorrenze, sizeof(int));
		close(p1p0[WRITE]);
		signal(SIGUSR1,vittoria);
		signal(SIGUSR2,sconfitta);		
		fclose(f);
		return occorrenze;
	}
	
int numero_occorrenze2(int valore, int elementi) {
		FILE* f;
		int i, s;
		int occorrenze=0;
		f=fopen(nomefile, "rb");
		close(p2p0[READ]);
		fseek(f,0,SEEK_SET);
		for(i=0;i<elementi;i++) {
			fread(&s,sizeof(int),1,f);
			if(s==valore) {
				occorrenze++;
			}
		}
		write(p2p0[WRITE], &occorrenze, sizeof(int));
		close(p2p0[WRITE]);
		signal(SIGUSR1,vittoria);
		signal(SIGUSR2,sconfitta);		
		fclose(f);
		return occorrenze;
	}
Il programma funziona, ovvero i due processi contano esattamente il numero di occorrenze. L'unico problema è che viene visualizzato solo il messaggio del pareggio e non quelli di vittoria o sconfitta. Probabilmente sarà sbagliato l'uso e la gestione dei segnali. Come risolvo il problema?
Grazie!

4 Risposte

  • Re: Pipe e segnali

    I figli fanno si la signal per sapere come gestire il segnale ricevuto, ma terminano prima di ricevere il segnale corretto.
    Soluzione 1 (brutta) prima della terminazione dei figli (exit(0)) metti una sleep di qualche secondo, è utile a verificare che effettivamente funzioni il tutto, ma orribile a vedersi.
    Soluzione 2 prima della terminazione dei figli inserisci una waitpid sul pid del padre (che ottieni con getppid()), ma attenzione che il padre potrebbe essere già morto quindi i tuoi processi ereditari da init (pid=1) e quindi finire in deadlock.
    Soluzione 3 (consigliata) comunicare con i processi tramite pipe o coda di messaggi anche i messaggi di vittoria e sconfitta in modo da rendere i processi bloccati in attesa di una risposta dal padre.
  • Re: Pipe e segnali

    Quindi dove devo fare l'invio e la cattura dei segnali? Potresti scrivermi un esempio di codice per favore??? Grazie!
  • Re: Pipe e segnali

    L'invio di segnali è corretto il problema è che i tuoi figli potenzialmente terminano prima di aver ricevuto il segnale, oppure lo ricevono quando ancora non sanno come trattarlo: sposta la signal all'inizio del codice dei figli e poi prima dell'exit(0) inserisci una sleep(5), dovrebbe bastare se il file non è troppo lungo. Inoltre la lettura dalle pipe del padre è bloccante? (Lo chiedo perché non ho mai usato pipe)
  • Re: Pipe e segnali

    Inoltre cambia la exit(0) dei figli in _exit(0)
Devi accedere o registrarti per scrivere nel forum
4 risposte