/* Soluzione parte C: per la sincronizzazione dei figli occorre creare uno schema di pipe, ossia una pipe che colleghi ogni figlio a quello precedente e successivo. Si noti che il primo processo figlio ha la pipe collegata al padre, e che l'ultimo processo figlio parte in maniera indipendente. Si scrivera' sempre sulla pipe i e si leggera' da quello (i+1): figlio N-1 == pipe N-1 ==> figlio N-2 == pipe N-2 ==> ... figlio i == pipe i ==> in particolare il primo figlio e' collegato al padre tramite la pipe 0 */ #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 corrispondente al carattere numerico e il PID del processo figlio corrente. Questa struttura verra' passata tramite le pipe da un figlio all'altro. */ typedef struct { int PID; /* ha il significato del campo c1 del testo */ int numero; /* ha il significato del campo c2 del testo */ } s_num; /* 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; /* Array di pipe usate a pipeline da ultimo figlio, al penultimo figlio .... primo figlio e poi a padre: ogni processo (a parte il primo) legge dalla pipe i+1 e scrive sulla pipe i */ 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_num cur_num; /* struttura che ogni figlio deve usare */ s_num pipe_num; /* struttura che verra' letta dalla pipe */ char ritorno; /* variabile per valore di ritorno per maggiore chiarezza, anche se in questo caso non serviva */ /* controllo sul numero dei parametri: non richiesto ma non ha senso se non abbiamo almeno due file e 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 e' pari al numero di file passati come argomento, quindi argc-1 */ N = argc-1; /* 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(2); } for (i=0; i= cur_num.numero) { cur_num.numero = pipe_num.numero; cur_num.PID = pipe_num.PID; } } /* invio i dati */ /* printf("sto per inviare numero=%d e pid=%d\n", cur_num.numero, cur_num.PID); */ write(p[i][1],&cur_num,sizeof(s_num)); } /* salvo il valore di ritorno anche se non serve, per maggiore leggibilita' */ ritorno = ch; /* termino il processo ritornando l'ultimo carattere (che e' sicuramente 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