Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 16 LUGLIO 2014
- La parte in C accetta un numero variabile di parametri N+1 (maggiore o uguale a 2, da controllare) che
- rappresentano i primi N i nomi assoluti di file F1...FN e l’ultimo la lunghezza in linee dei file (X, da non
- controllare). Il processo padre deve generare N processi figli (P0 … PN-1): ogni processo figlio è associato al
- corrispondente file Fi. Ognuno di tali processi figli esegue concorrentemente, leggendo tutte le X linee del file
- associato Fi: per ogni linea letta, il figlio Pi deve selezionare il primo carattere e quindi comunicare questa
- informazione. In particolare, i processi figli e il processo padre devono attenersi ad uno schema di
- comunicazione a pipeline; il figlio P0 comunica con il figlio P1 etc. fino al figlio PN-1 che comunica con il
- padre; questo schema a pipeline deve essere ripetuto per ogni linea di ogni file e deve prevedere l’invio in avanti
- di un array di caratteri (primiCar) di grandezza pari al numero di linee dei file; il primo figlio P0, dopo aver
- completato la lettura della linea corrente letta dal file associato F1, inserisce in primiCar al primo posto il primo
- carattere della linea corrente e quindi invia primiCar al figlio P1; quindi ogni figlio Pi (a parte P0) deve
- ricevere primiCar e quindi deve inserire, dopo aver completato la lettura della linea corrente letta dal file
- associato Fi, in primiCar al posto corretto il primo carattere della linea corrente e quindi invia avanti primiCar
- al figlio successivo, fino a PN-1 che la invia al processo padre. Quindi, al processo padre devono arrivare tanti
- array primiCar quante sono le linee dei file letti dai processi figli P0 … PN-1. Il padre ha il compito di
- stampare su standard output tutte le informazioni ricevute dal processo PN-1: in particolare, deve essere
- stampato -per ogni linea- un contatore di linea e quindi i primi caratteri letti da ogni processo figlio riportando
- anche -per ogni carattere- l’indice del processo che ha effettuato la lettura e il nome del file da cui si è letto tale
- carattere.
- Al termine, ogni processo figlio Pi deve ritornare al padre l’ultimo carattere selezionato dal proprio file associato
- Fi e il padre deve stampare su standard output il PID di ogni figlio e il valore ritornato.
- /* Soluzione della parte C del compito del 16 Luglio 2014 */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <fcntl.h>
- typedef int pipe_t[2];
- int main (int argc, char **argv)
- {
- int N; /* numero di file */
- int X; /* numero di linee */
- int pid; /* pid per fork */
- pipe_t *pipes; /* array di pipe usate a pipeline da primo figlio, a secondo figlio .... ultimo figlio e poi a padre: ogni processo legge dalla pipe i-1 e scrive sulla pipe i */
- int i,j; /* contatori */
- int fd; /* file descriptor */
- int pidFiglio, status, ritorno; /* per valore di ritorno figli */
- char *primiCar; /* array dinamico di caratteri che i figli si passeranno in pipeline e che arriverà al padre */
- char ch, chprimo; /* carattere letto da linea e carattere da inserire nell'array */
- int nr,nw; /* variabili per salvare valori di ritorno di read e write da/su pipe */
- /* int linee = 1; serve per mantenere il numero corrente della linea e e' stata usata solo nelle stampe di controllo */
- if (argc < 3)
- {
- printf("Errore numero di parametri\n");
- exit(1);
- }
- X = atoi(argv[argc-1]);
- printf("Numero di linee %d\n", X);
- /* controllo non richiesto, ma inserito per sicurezza */
- if (X < 0)
- {
- printf("Errore numero linee: non maggiore di zero\n");
- exit(2);
- }
- N = argc-2;
- printf("Numero di processi da creare %d\n", N);
- /* allocazione primiCar: la fa il padre e tutti i figli lo otterranno per copia */
- if ((primiCar=(char *)malloc(N*sizeof(char))) == NULL)
- {
- printf("Errore allocazione primiCar\n");
- exit(3);
- }
- /* allocazione pipe */
- if ((pipes=(pipe_t *)malloc(N*sizeof(pipe_t))) == NULL)
- {
- printf("Errore allocazione pipe\n");
- exit(4);
- }
- /* creazione pipe */
- for (i=0;i<N;i++)
- if(pipe(pipes[i])<0)
- {
- printf("Errore creazione pipe\n");
- exit(5);
- }
- /* creazione figli */
- for (i=0;i<N;i++)
- {
- if ((pid=fork())<0)
- {
- printf("Errore creazione figli\n");
- exit(6);
- }
- else if (pid==0)
- { /* codice figlio */
- printf("Sono il figlio %d\n", getpid());
- /* chiusura pipes inutilizzate */
- for (j=0;j<N;j++)
- {
- if (j!=i)
- close (pipes[j][1]);
- if ((i == 0) || (j != i-1))
- close (pipes[j][0]);
- }
- /* apertura file */
- if ((fd=open(argv[i+1],O_RDONLY))<0)
- {
- printf("Impossibile aprire il file %s\n", argv[i+1]);
- exit(7);
- }
- j = 0;
- while(read(fd,&ch,1)>0)
- {
- if (j == 0) /* se e' il primo carattere della linea allora lo salviamo in chprimo */
- {
- chprimo = ch;
- /* stampa di controllo
- printf("processo di indice %d ha salvato il carattere %c per la linea %d\n",i, chprimo, linee);
- */
- }
- /* controllo fine linea */
- if (ch == '\n') /* siamo a fine linea */
- {
- /* linee++; introdotto solo per stampe di controllo */
- if (i!=0) /* il primo figlio NON deve leggere dal figlio precedente l'array */
- {
- nr=read(pipes[i-1][0],primiCar, N);
- if (nr!=N)
- {
- printf("Errore in lettura da pipe[%d]\n",i);
- exit(8);
- }
- }
- /* in ogni modo, quindi sia per il primo figlio che per gli altri, deve essere inserito il carattere al posto giusto */
- primiCar[i] = chprimo;
- /* comunicazione primiCar al figlio seguente */
- nw=write(pipes[i][1], primiCar, N);
- if (nw!=N)
- {
- printf("Errore in scrittura da pipe[%d]\n",i);
- exit(9);
- }
- j = 0; /* riazzeriamo il conteggio dei caratteri della linea */
- }
- else
- {
- j++; /* incrementiamo il conteggio dei caratteri della linea */
- }
- }
- exit(chprimo);
- }
- } /* fine for */
- /* codice del padre */
- /* chiusura pipe: tutte meno l'ultima in lettura */
- for(i=0;i<N;i++)
- {
- close (pipes[i][1]);
- if (i != N-1) close (pipes[i][0]);
- }
- /* il padre deve leggere X strutture, tante quante sono le linee lette dai figli */
- for(j=0;j<X;j++)
- {
- read(pipes[N-1][0], primiCar, N);
- printf("Ricevuto per la linea %d i seguenti primi caratteri:\n", j+1); /* incrementiamo j in modo da rendere piu' chiaro a che linea ci stiamo riferendo */
- for(i=0;i<N;i++)
- printf("Carattere %c ricevuto dal processo di indice %d per il file %s\n", primiCar[i], i, argv[i+1]);
- }
- /* Il padre aspetta i figli */
- for (i=0; i < N; i++)
- {
- pidFiglio = wait(&status);
- if (pidFiglio < 0)
- {
- printf("Errore in wait\n");
- exit(10);
- }
- if ((status & 0xFF) != 0)
- printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
- else
- { ritorno=(int)((status >> 8) & 0xFF);
- printf("Il figlio con pid=%d ha ritornato %c\n", pidFiglio, ritorno);
- }
- }
- return(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement