/* Soluzione della Prova d'esame del 16 Giugno 2009 - Parte C */ #include #include #include #include #include #include #include typedef int pipe_t[2]; int main(int argc, char **argv) { /* -------- Variabili locali ---------- */ int pid; /* process identifier per le fork() */ int N; /* numero di file passati sulla riga di comando */ int retVal; /* return value che il figlio passa al padre alla fine */ int fdr; /* variabile per file descriptor figlio */ int status; /* variabile di stato per la wait */ pipe_t *piped; /* array dinamico di pipe descriptors */ int i, j; /* indici per i cicli */ int k; /* variabile per capire se primo car. numerico */ char cn; /* variabile dove i figli mettono in carattere da cercare */ char ch; /* carattere di appoggio dei figli per leggere */ /* ------------------------------------ */ /* Controllo sul numero di parametri */ if (argc < 3) /* Meno di due parametri */ { printf("Errore nel numero dei parametri: devono essere almeno due!\n"); exit(-1); } /* Calcoliamo il numero di file passati e quindi di processi da creare */ N = argc - 1; /* Controlliamo che siano in numero pari */ if (N % 2) { printf("Errore il numero di parametri deve essere pari!\n"); exit(-2); } /* Allocazione dell'array di N/2 pipe descriptors*/ piped = (pipe_t *) malloc (N/2*sizeof(pipe_t)); if (piped == NULL) { printf("Errore nella allocazione della memoria"); exit(-3); } /* Creazione delle N/2 pipe fra le coppie di figli */ for (i=0; i < N/2; i++) { if(pipe(piped[i]) < 0) { printf("Errore nella creazione della pipe"); exit(-4); } } printf("Sono il padre con PID=%d \n", getpid()); /* Ciclo di generazione dei figli */ for (i=0; i < N; i++) { if ( (pid = fork()) < 0) { printf("Errore nella fork."); exit(-5); } if (pid == 0) /* codice del figlio */ { printf("Sono il figlio con PID=%d e i=%d\n", getpid(), i); /* Chiusura dei lati non utilizzati delle pipe */ for (j=0; j < N; j++) { if ((!(i % 2))&&(j==(i/2))) /* pari, pipe usata in scrittura */ close(piped[j][0]); else if ((i%2)&&(j==((i-1)/2))) /* dispari, pipe usata in lettura */ close(piped[j][1]); else { /* j corrisponde ad una pipe non usata per il figlio con * questo indice */ close(piped[j][0]); close(piped[j][1]); } } /* apre in sola lettura il file argv[i+1] */ if ((fdr = open(argv[i+1], O_RDONLY)) < 0) { printf("Errore in apertura del file %s\n", argv[i+1]); exit(-6); } retVal = 0; k = 0; while(read(fdr, &ch, 1) > 0) { if (isdigit(ch)) /* ho trovato un carattere numerico */ { k++; if (!(i %2)) /* pari */ { if (k == 1) /* primo car. numerico */ { cn = ch; /* il figlio pari spedisce al figlio dispari della coppia il primo carattere numerico trovato */ write(piped[i/2][1], &cn, 1); } } else /* dispari */ if (k == 1) /* primo car. numerico */ /* il figlio dispari riceve dal figlio pari della coppia il carattere numerico da cercare */ read(piped[(i-1)/2][0], &cn, 1); /* sia nel caso pari che dispari, incremento il conteggio se ho trovato il carattere da cercare */ if (ch == cn) retVal++; } } exit(retVal); /* fine codice del figlio */ } } /* Codice del padre */ for (i=0; i < N; i++) close(piped[i][1]); /* Il padre aspetta i figli */ for (i=0; i < N; i++) { pid = wait(&status); printf("Il figlio con pid=%d ha ritornato %d\n", pid, (int)((status >> 8) & 0xFF)); } return(0); }