/* Soluzione parte C: per la sincronizzazione dei figli occorre creare uno schema di pipe "circolare", ossia una pipe che colleghi ogni figlio a quello precedente e successivo. Si noti che l'ultimo processo figlio ha la pipe collegata al padre, e che il primo processo figlio parte in maniera indipendente. Si scriverà sempre sul lato i+1 e si leggerà da quello i: figlio 0 == pipe 1 ==> figlio 1 == pipe 2 ==> ... figlio i == pipe i+1 ==> ma l'ultimo figlio è collegato al padre tramite una pipe (i+1)%n = 0 */ /* SI PRECISA CHE RISPETTO AL TESTO FORNITO QUESTA SOLUZIONE INVECE CHE PASSARE AL PADRE IL VALORE MINIMO DELLE OCCORRENZE CONTATE, PASSA IL MASSIMO: NEL CODICE SI RIPORTERA' UN ULTERIORE COMMENTO IN CORRISPONDENZA DEL TEST CHE BASTA INVERTIRE PER AVERE IL COMPORTAMENTO RICHIESTO DAL TESTO FORNITO. */ #include #include #include #include #include #include /* definisco un tipo per un array di due interi */ typedef int pipe_t[2]; /* definizione di una struttura dati che racchiuda il numero di occorrenza del carattere e il PID del processo figlio corrente. Questa struttura verra' passata tramite le pipe da un figlio all'altro. */ typedef struct { int occorrenza; int PID; } s_occ; /* Inizio del programma vero e proprio */ int main(int argc, char **argv) { int n; /* Numero di processi figli da creare */ int i; /* Contatore per la generazione delle pipe/figli*/ int j; /* Contatore per la chiusura dei lati non usati delle pipe */ pipe_t *p; /* Puntatore ad un array di pipe */ char chpassato; /*carattere passato come parametro*/ char ch; /*carattere utilizzato nella read del file*/ int status; /*utilizzato come status di ritorno dei figli*/ int fd; /*file descriptor generico */ int pid; /* valore di ritorno della fork o pid del processo corrente */ s_occ cur_occ; /* struttura che ogni figlio deve usare */ s_occ pipe_occ; /* struttura che verrà passata lungo la pipe */ int ritorno; /*variabile per valore di ritorno */ /* controllo sul numero dei parametri: devo avere almeno un file e un carattere quindi almeno tre argomenti (argv[0] compreso) */ if( argc < 3) { printf("Uso: %s num variabile di file, almeno 2\n", argv[0]); exit(1); } /* il numero di figli da generare è pari al numero di file passati come argomento, quindi argc-2 */ n = argc-2; if (strlen(argv[argc-1]) != 1) { printf("L'ultimo parametro non è un singolo carattere, ma è una stringa: %s\n", argv[argc-1]); exit(2); } /* il numero di figli da generare è pari al numero di file passati come argomento, quindi argc-2 */ /* il carattere passato come parametro si trova nell'ultima posizione della lista degli argomenti, ossia argc-1 */ chpassato=argv[argc-1][0]; /* allocazione delle pipe: occorre un numero di pipe pari al numero di figli (una viene usata per la comunicazione con il padre) */ p = (pipe_t *)malloc(sizeof(pipe_t)*n); if( p == NULL ) { printf("Impossibile allocare il vettore di pipe\n"); exit(3); } for(i=0; i= cur_occ.occorrenza ){ cur_occ.occorrenza = pipe_occ.occorrenza; } } /* invio i dati */ /* printf("sto per inviare occ=%d e pid=%d\n", cur_occ.occorrenza, cur_occ.PID); */ write(p[(i+1)%n][1],&cur_occ,sizeof(s_occ)); /* chiudo le pipe che ho usato */ close(p[(i+1)%n][1]); close(p[i][0]); /* termino il processo ritornando il valore delle occorrenze (supposto minore di 255) */ exit(ritorno); } /* FINE CODICE DEL FIGLIO */ } /* fine del ciclo for */ /* CODICE DEL PADRE */ /* chiudo tutte le pipe non usate */ for (j=0;j