#include #include #include #include #include #include int main (int argc, char **argv) { int N; /* numero di file passati (pari) */ int i; /* indice */ int H; /* numero di processi figli */ int pid, pid2; /* pid per figli e nipoti */ int status; /* stato di ritorno del nipote e del figlio */ int scritti; /* numero blocchi scritti dal nipote sul file */ int fdrn,fdrf,fds; /* fd per lettura nipote e figlio e per scrittura nipote */ int piped[2]; /* pipe di comunicazione per ogni coppia figlio-nipote */ char *nomefile; /* nome del file che deve creare il nipote */ char buffer1[11]; /* buffer di lettura da file per nipote e figlio */ char buffer2[11]; /* buffer di lettura da pipe per il nipote */ if (argc < 3) { printf("Ci vogliono almeno due nomi di file\n"); exit(1); } N = argc - 1; /* numero di file */ if ((N%2)!=0) { printf("Ci vuole un numero pari di parametri\n"); exit(2); } H = N/2; /* numero di figli */ printf("Padre: %d genera %d figli\n",getpid(),H); for (i=1;i<=H;i++) /* l'indice lo facciamo iniziare da 1! */ { pid=fork(); if (pid<0) { printf("Errore nella %d-esima fork\n",i); exit(3); } if (pid==0) /*figlio*/ { printf("Figlio: %d del padre: %d\n",getpid(),getppid()); if ((pipe(piped))<0) { printf("Errore nella %d pipe\n",i); exit(-1); /* in caso di errori nei figli o nei nipoti decidiamo di tornare -1 che corrispondera' per il padre al valore 255 che non puo' essere un valore accettabile di ritorno */ } pid2=fork(); if (pid2<0) { printf("Errore nella %d-esima fork (nipote)\n",i); exit(-1); } if (pid2==0) /*nipote*/ { printf("Nipote: %d del figlio: %d\n",getpid(),getppid()); fdrn=open(argv[i+H],O_RDONLY); if (fdrn<0) { printf("Errore nell'apertura del file: %s\n",argv[i+H]); exit(-1); } nomefile=(char *)malloc(strlen(argv[i+H])+9); /* sommiamo 9 perche' la stringa ".blocchi" e' di 8 caratteri e poi dobbiamo includere il terminatore*/ if (nomefile==NULL) { printf("Errore nell'allocazione di memoria\n"); exit(-1); } strcpy(nomefile,argv[i+H]); strcat(nomefile,".blocchi"); fds=creat(nomefile,0644); if (fds<0) { printf("Errore nella creazione del file: %s\n",nomefile); exit(-1); } close(piped[1]); /* chiudo lato pipe non usato dal nipote */ scritti=0; /* si deve inizializzare il contatore di blocchi scritti che andra' tornato al figlio */ while ((read(fdrn, buffer1, 11))==11) { read(piped[0], buffer2, 11); /* confrontiamo il contenuto dei due buffer */ if ((memcmp(buffer1, buffer2, 11)) == 0) write(fds, buffer2, 11); /* sono uguali e quindi e' indifferente quale scrivere */ else /* devono essere scritti 11 caratteri 'spazio' */ write(fds," ",11); scritti++; /* incrementiamo in ogni caso il contatore */ } exit(scritti); /* torniamo al figlio */ } else { /* figlio */ fdrf=open(argv[i],O_RDONLY); if (fdrf<0) { printf("Errore nell'apertura del file: %s\n",argv[i]); exit(-1); } close(piped[0]); /* chiudo lato della pipe non usato dal figlio */ while ((read(fdrf, buffer1, 11))==11) { write(piped[1], buffer1, 11); } /* aspettiamo il nipote */ pid=wait(&status); if (pid < 0) { printf("Errore in wait\n"); exit (-1); } if ((status & 0xFF) != 0) { printf("Nipote con pid %d terminato in modo anomalo\n", pid); exit (-1); } else { scritti = (status>>8)&(0xFF); printf("Terminato nipote %d e ritornato %d\n", pid, scritti); exit(scritti); /* il figlio ritorna al padre quanto gli ha ritornato il figlio */ } } } } /* Il padre aspetta i figli */ for (i=1;i<=H;i++) { pid = wait(&status); if (pid < 0) { printf("Errore in wait\n"); exit(4); } if ((status & 0xFF) != 0) printf("Figlio con pid %d terminato in modo anomalo\n", pid); else printf("Terminato figlio: %d con valore di ritorno (se 255 problemi in figlio o nipote): %d\n",pid,(status>>8)&(0xFF)); } exit(0); }