/* Soluzione della Prova d'esame dell'13 Marzo 2009 - Parte C */ #include #include #include #include #include #include #include typedef int pipe_t[2]; typedef struct { char cell[11]; char cognome[18]; char nome[18]; } voce_rubrica; 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 rc; /* 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 */ char stringa[18]; /* variabile dove il padre mette la stringa che i figli devono cercare */ voce_rubrica v_rub; /* variabile preparata dal figlio per spedizione al padre */ char ch; /* carattere di appoggio per scartare separatori (\t e \n) */ /* ------------------------------------ */ /* Controllo sul numero di parametri */ if (argc < 3) /* Meno di due parametri */ { printf("Errore nel numero dei parametri: devono essere in numero pari!\n"); exit(-1); } /* Calcoliamo il numero di file passati e quindi di processi da creare */ N = argc - 1; /* Leggiamo stringa che i figli devono trovare */ printf("Dammi un cognome che deve essere cercato nei file rubrica (max. 17 caratteri)\n"); scanf("%s", stringa); printf("Cognome letto %s\n", stringa); /* Allocazione dell'array di N pipe descriptors*/ piped = (pipe_t *) malloc (N*sizeof(pipe_t)); if (piped == NULL) { printf("Errore nella allocazione della memoria"); exit(-2); } /* Creazione delle N pipe padre-figli */ for (i=0; i < N; i++) { if(pipe(piped[i]) < 0) { printf("Errore nella creazione della pipe"); exit(-3); } } 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(-4); } 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++) { close(piped[j][0]); if (j!=i) 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(-5); } rc = 0; while(read(fdr, &(v_rub.cell), 11) > 0) { printf("cellulare letto %s da i=%d\n", v_rub.cell, i); read(fdr,&ch,1); /* si scarta il primo \t */ read(fdr, &(v_rub.cognome), 18); printf("cognome letto %s da i=%d\n", v_rub.cognome, i); read(fdr,&ch,1); /* si scarta il secondo \t */ read(fdr, &(v_rub.nome), 18); printf("nome letto %s da i=%d\n", v_rub.nome, i); read(fdr,&ch,1); /* si scarta lo \n */ if (strcmp(v_rub.cognome, stringa) == 0) /* ho trovato la voce della rubrica che devo mandare al padre */ { printf("Sono il figlio con PID=%d e i=%d la stringa da cercare is %s\n", getpid(), i, stringa); /* contiamo quante strutture mandiamo al padre */ rc++; /* comunico la struttura al padre */ write(piped[i][1], &v_rub, sizeof(v_rub)); } } exit(rc); /* fine codice del figlio */ } } /* Codice del padre */ for (i=0; i < N; i++) close(piped[i][1]); /* Il padre recupera le informazioni dai figli in ordine di indice */ for (i=0; i < N; i++) { /* il padre deve recuperare tutte le strutture inviate da ogni figlio */ while (read(piped[i][0], &v_rub, sizeof(v_rub)) > 0) { printf("Figlio %d ha trovato il cellulare %s\n", i, v_rub.cell); printf("con cognome %s\n", v_rub.cognome); printf("e con nome %s\n", v_rub.nome); } } /* 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); }