/* Soluzione della Prova d'esame del 10 Settembre 2025: la comunicazione in ogni coppia va dal secondo processo della coppia al primo processo della coppia ed e' il primo processo della coppia deve creare il file con terminazione ".max" sul quale poi deve scrivere */ #include #include #include #include #include #include #define PERM 0644 typedef int pipe_t[2]; 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 */ /* nome indicato nel testo */ int n; /* indice per i figli */ /* nome indicato nel testo */ pipe_t *pipe_ps; /* array di pipe per la comunicazione dai figli secondi della coppia ai figli primi della coppia */ int i, j; /* indici per i cicli */ char *FCreato; /* variabile per nome file da creare da parte dei processi figli primi della coppia */ int fcreato; /* file descriptor per creazione file da parte dei processi figli primi della coppia */ /* nome indicato nel testo */ int fd; /* file descriptor per apertura file */ char Car; /* carattere per leggere dai file */ /* nome indicato nel testo */ char CarLetto; /* variabile usata dal figlio primo della coppia per recuperare il carattere inviato dal figlio secondo della coppia */ char CarMax; /* variabile usata dai figli per calcolare il proprio massimo */ long int nroCar; /* variabile usata dai figli per calcolare la posizione del carattere: ATTENZIONE DEVE ESSERE UN LONG INT */ int status, ritorno; /* variabili per la wait */ /* ------------------------------------ */ /* Controllo sul numero di parametri */ if (argc < 2) /* Meno di un parametro */ { printf("Errore nel numero dei parametri dato che argc=%d (bisogna passare almeno un nome di file!)\n", argc); exit(1); } /* Calcoliamo il numero di file passati */ N = argc - 1; printf("Sono il padre con pid %d e %d file e creero' %d processi figli\n", getpid(), N, 2*N); /* allocazione memoria dinamica per pipe_ps. NOTA BENE: servono un numero di pipe che e' la meta' del numero di figli e quindi solo N! */ pipe_ps = (pipe_t *) malloc (N*sizeof(pipe_t)); if (pipe_ps == NULL) { printf("Errore nella allocazione della memoria per le pipe\n"); exit(2); } /* Creazione delle N pipe: ATTENZIONE VANNO CREATE solo N pipe */ for (i=0; i < N; i++) { if(pipe(pipe_ps[i]) < 0) { printf("Errore nella creazione della pipe\n"); exit(3); } } /* Ciclo di generazione dei figli: NOTA BENE DEVONO ESSERE 2 * N */ for (n=0; n < 2*N; n++) { if ( (pid = fork()) < 0) { printf("Errore nella fork del figlio %d-esimo\n", n); exit(4); } if (pid == 0) { /* codice del figlio: in caso di errore torniamo -1 che non e' un valore accettabile per un carattere */ if (n < N) /* siamo nel codice dei figli primi della coppia */ { /* stampa di debugging */ printf("DEBUG-PRIMO DELLA COPPIA-Figlio di indice %d e pid %d associato al file %s\n",n,getpid(),argv[n+1]); /* i figli primi della coppia devono creare il file specificato */ FCreato=(char *)malloc(strlen(argv[n+1]) + 5); /* bisogna allocare una stringa lunga come il nome del file associato + il carattere '.' + i caratteri della parola max (3) + il terminatore di stringa */ if (FCreato == NULL) { printf("Errore nella malloc per nome file da creare\n"); exit(-1); } /* copiamo il nome del file associato */ strcpy(FCreato, argv[n+1]); /* concateniamo la stringa specificata dal testo */ strcat(FCreato,".max"); if ((fcreato=creat(FCreato, PERM)) < 0) { printf("Impossibile creare il file %s\n", FCreato); exit(-1); } /* chiudiamo le pipe che non servono */ /* ogni figlio PRIMO della coppia legge solo da pipe_ps[n] */ for (j=0;j CarMax) CarMax=Car; /* dobbiamo ricevere dal secondo processo della coppia il carattere */ read(pipe_ps[n][0], &CarLetto, 1); if (Car > CarLetto) { /* se il carattere del primo figlio della coppia e' maggiore, scriviamo quello sul file */ write(fcreato, &Car, 1); } else { /* altrimenti scriviamo quello ricevuto sul file */ write(fcreato, &CarLetto, 1); } } nroCar++; /* incrementiamo il contatore */ } } else /* siamo nel codice dei figli secondi della coppia */ { /* stampa di debugging */ printf("DEBUG-SECONDO DELLA COPPIA-Figlio di indice %d e pid %d associato al file %s\n",n,getpid(),argv[n-N+1]); /* chiudiamo le pipe che non servono */ /* ogni figlio SECONDO della coppia scrive solo su pipe_ps[n-N] */ for (j=0;j CarMax) CarMax=Car; /* dobbiamo inviare al primo processo della coppia il carattere */ write(pipe_ps[n-N][1], &Car, 1); } nroCar++; /* incrementiamo il contatore */ } } /* ogni figlio deve ritornare al padre il carattere corrispondente al minimo */ exit(CarMax); } } /* Codice del padre */ /* Il padre chiude tutti i lati delle pipe dato che non le usa */ for (i=0; i < N; i++) { close(pipe_ps[i][0]); close(pipe_ps[i][1]); } /* Il padre aspetta tutti i figli */ for (n=0; n < 2*N; n++) { pid = wait(&status); if (pid < 0) { printf("Errore in wait\n"); exit(5); } if ((status & 0xFF) != 0) printf("Figlio con pid %d terminato in modo anomalo\n", pid); else { ritorno=(int)((status >> 8) & 0xFF); printf("Il figlio con pid=%d ha ritornato %c (%d in decimale, se 255 problemi)\n", pid, ritorno, ritorno); /* i figli tornano un carattere e quindi bisogna usare il formato %c, poi per intercettare i casi di errori si puo' aggiungere la stampa anche in decimale! */ } } exit(0); }