Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- La parte in C accetta un numero variabile N di parametri che rappresentano nomi di file (F0, F1, ... FN-1).
- Il processo padre deve generare N processi figli Pi (P0 … PN-1): ogni processo figlio è associato al corrispondente file
- Fi. Ognuno di tali processi figli deve creare a sua volta un processo nipote PPi (PP0 … PPN-1) associato sempre al
- corrispondente file Fi. Ogni processo figlio Pi e ogni nipote PPi esegue concorrentemente andando a cercare nel file
- associato Fi tutte le occorrenze dei caratteri alfabetici maiuscolo per il figlio e tutte le occorrenze dei caratteri numerici
- per il nipote. Ognuno dei processi figlio e nipote deve operare una modifica del file Fi: in specifico, ogni figlio deve
- trasformare ogni carattere alfabetico maiuscolo nel corrispondente carattere alfabetico minuscolo, mentre ogni nipote
- deve trasformare ogni carattere numerico nel carattere spazio. Una volta terminate le trasformazioni, sia i processi figli
- Pi che i processi nipoti PPi devono comunicare al padre il numero (in termini di long int) di trasformazioni effettuate.
- Il padre ha il compito di stampare su standard output, rispettando l'ordine dei file, il numero di trasformazioni ricevute
- da ogni figlio Pi e da ogni nipote PPi, riportando opportuni commenti esplicativi: ad esempio “nel file F0 sono stati
- trasformati tot1 caratteri alfabetici maiuscolo in caratteri alfabetici minuscolo e tot2 caratteri numerici nel carattere
- spazio”.
- Al termine, ogni processo nipote PPi deve ritornare al figlio Pi un opportuno codice ed analogamente ogni processo
- figlio Pi deve ritornare al padre un opportuno codice; il codice che ogni nipote PPi e ogni figlio Pi deve ritornare è:
- a) 0 se il numero di trasformazioni attuate è minore di 256;
- b) 1 se il numero di trasformazioni attuate è maggiore o uguale a 256, ma minore di 512;
- c) 2 se il numero di trasformazioni attuate è maggiore o uguale a 512, ma minore di 768;
- d) etc.
- Sia ogni figlio Pi e sia il padre devono stampare su standard output il PID di ogni nipote/figlio e il valore ritornato.
- /* Soluzione della Prova d'esame del 14 Settembre 2011 - Parte C */
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/wait.h>
- #include <ctype.h>
- 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 */
- int status; /* variabile di stato per la wait */
- pipe_t *pipedFP; /* array dinamico di pipe descriptors per comunicazioni figli-padre */
- pipe_t *pipedNP; /* array dinamico di pipe descriptors per comunicazioni nipoti-padre */
- int fd; /* file descriptor che serva sia ai figli che ai nipoti */
- int i, j; /* indici per i cicli */
- char ch; /* variabile che serve per leggere i caratteri sia da parte dei figli che dei nipoti */
- long int trasformazioni=0; /* variabile che mantiene il numero delle trasformazioni effettuate sia dai figli che dai nipoti */
- int ritorno; /* variabile che viene ritornata da ogni figlio al padre e da ogni nipote al figlio */
- /* ------------------------------------ */
- /* Controllo sul numero di parametri (anche se non richiesto, dato che con meno di due parametri ha poco senso) */
- if (argc < 3) /* Meno di due parametri */
- {
- printf("Errore nel numero dei parametri\n");
- exit(1);
- }
- /* Calcoliamo il numero di file/numeri passati */
- N = argc - 1;
- /* Allocazione dell'array di N pipe descriptors figli-padre */
- pipedFP = (pipe_t *) malloc (N*sizeof(pipe_t));
- if (pipedFP == NULL)
- {
- printf("Errore nella allocazione della memoria pipe figli-padre\n");
- exit(2);
- }
- /* Allocazione dell'array di N pipe descriptors nipoti-padre */
- pipedNP = (pipe_t *) malloc (N*sizeof(pipe_t));
- if (pipedNP == NULL)
- {
- printf("Errore nella allocazione della memoria pipe nipoti-padre\n");
- exit(3);
- }
- /* Creazione delle N pipe figli-padre e delle N pipe nipoti-padre */
- for (i=0; i < N; i++)
- {
- if (pipe(pipedFP[i]) < 0)
- {
- printf("Errore nella creazione della pipe %d-esima figli-padre\n", i);
- exit(4);
- }
- if (pipe(pipedNP[i]) < 0)
- {
- printf("Errore nella creazione della pipe %d-esima nipoti-padre\n", i);
- exit(5);
- }
- }
- /* Ciclo di generazione dei figli */
- for (i=0; i < N; i++)
- {
- if ( (pid = fork()) < 0)
- {
- printf("Errore nella fork %d-esima\n", i);
- exit(6);
- }
- if (pid == 0)
- {
- /* codice del figlio */
- printf("Sono il processo figlio di indice %d e pid %d sto per creare il nipote che leggera' sempre dal mio stesso file %s\n", i, getpid(), argv[i+1]);
- /* Chiusura delle pipe non usate nella comunicazione con il padre */
- for (j=0; j < N; j++)
- {
- close(pipedFP[j][0]);
- if (i != j) close(pipedFP[j][1]);
- }
- if ( (pid = fork()) < 0)
- {
- printf("Errore nella fork di creazione del nipote\n");
- exit(-1); /* decidiamo, in caso di errore, di tornare -1 che verra' interpretato come 255 e quindi un valore NON accettabile */
- }
- if (pid == 0)
- {
- /* codice del nipote */
- printf("Sono il processo nipote del figlio di indice %d e pid %d\n", i, getpid());
- /* chiusura della pipe rimasta aperta di comunicazione fra figlio-padre che il nipote non usa */
- close(pipedFP[i][1]);
- /* Chiusura delle pipe non usate nella comunicazione con il padre */
- for (j=0; j < N; j++)
- {
- close(pipedNP[j][0]);
- if (i != j) close(pipedNP[j][1]);
- }
- /* sia il figlio che il nipote devono aprire (con due open separate per avere l'I/O pointer separato) lo stesso file in lettura/scrittura, dato che dovranno operare delle trasformazioni */
- if ((fd=open(argv[i+1], O_RDWR)) < 0)
- {
- printf("Errore nella open del file %s\n", argv[i+1]);
- exit(-1); /* decidiamo, in caso di errore, di tornare -1 che verra' interpretato come 255 e quindi un valore NON accettabile */
- }
- while (read(fd, &ch, 1))
- {
- /* controlliamo se abbiamo trovato un carattere numerico */
- if (isdigit(ch))
- /* si deve trasformare nel carattere spazio e quindi per prima cosa bisogna tornare indietro di una posizione */
- { lseek(fd, -1L, SEEK_CUR);
- ch = ' '; /* trasformiamo il carattere nello spazio */
- write(fd, &ch, 1); /* scriviamolo sul file */
- /* e aggiorniamo il numero di trasformazioni */
- trasformazioni++;
- }
- else
- ; /* non si deve fare nulla */
- }
- /* il nipote deve inviare al padre il numero di trasformazioni operate */
- write(pipedNP[i][1], &trasformazioni, sizeof(trasformazioni));
- ritorno=trasformazioni/256;
- exit(ritorno); /* torniamo il valore richiesto dal testo operando una divisione intera per 256 */
- }
- else
- { /* codice figlio */
- /* le pipe usate dal nipote vanno chiuse TUTTE */
- for (j=0; j < N; j++)
- {
- close(pipedNP[j][0]);
- close(pipedNP[j][1]);
- }
- /* il figlio ha un codice molto simile al nipote, adesso il figlio legge dalla pipe fino a che ci sono caratteri e cioe' linee inviate dal nipote tramite la head */
- /* sia il figlio che il nipote devono aprire (con due open separate per avere l'I/O pointer separato) lo stesso file in lettura/scrittura, dato che dovranno operare delle trasformazioni */
- if ((fd=open(argv[i+1], O_RDWR)) < 0)
- {
- printf("Errore nella open del file %s\n", argv[i+1]);
- exit(-1); /* decidiamo, in caso di errore, di tornare -1 che verra' interpretato come 255 e quindi un valore NON accettabile */
- }
- while (read(fd, &ch, 1))
- {
- /* controlliamo se abbiamo trovato un carattere alfabetico MAIUSCOLO */
- if (isupper(ch))
- /* si deve trasformare nel corrispondente carattere alfabetico minuscolo e quindi per prima cosa bisogna tornare indietro
- di una posizione */
- { lseek(fd, -1L, SEEK_CUR);
- ch = ch + 32; /* trasformiamo il carattere da MAIUSCOLO a minuscolo aggiungendo 32 */
- write(fd, &ch, 1); /* scriviamolo sul file */
- /* e aggiorniamo il numero di trasformazioni */
- trasformazioni++;
- }
- else
- ; /* non si deve fare nulla */
- }
- /* il figlio deve inviare al padre il numero di trasformazioni operate */
- write(pipedFP[i][1], &trasformazioni, sizeof(trasformazioni));
- /* il figlio deve aspettare il nipote e stampare il suo pid con il valore ritornato (come richiesto dal testo) */
- 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);
- else
- printf("Il nipote con pid=%d ha ritornato %d\n", pid, ritorno=(int)((status >> 8) & 0xFF));
- /* torniamo il valore richiesto dal testo operando una divisione intera per 256 */
- ritorno=trasformazioni/256;
- exit(ritorno);
- }
- }
- }
- /* Codice del padre */
- /* Il padre chiude i lati delle pipe che non usa */
- for (i=0; i < N; i++)
- {
- close(pipedFP[i][1]);
- close(pipedNP[i][1]);
- }
- /* Il padre recupera le informazioni dai figli in ordine di indice */
- for (i=0; i < N; i++)
- {
- read(pipedFP[i][0], &trasformazioni, sizeof(trasformazioni));
- printf("Il figlio di indice %d ha operato %ld trasformazioni di caratteri MAIUSCOLI in minuscoli sul file %s\n", i, trasformazioni, argv[i+1]);
- read(pipedNP[i][0], &trasformazioni, sizeof(trasformazioni));
- printf("Il nipote di indice %d ha operato %ld trasformazioni di caratteri numerici in carattere spazio sullo stesso file %s\n", i, trasformazioni, argv[i+1]);
- }
- /* Il padre aspetta i figli */
- for (i=0; i < N; i++)
- {
- pid = wait(&status);
- if (pid < 0)
- {
- printf("Errore in wait\n");
- exit(7);
- }
- if ((status & 0xFF) != 0)
- printf("Figlio con pid %d terminato in modo anomalo\n", pid);
- else
- { ritorno=(int)((status >> 8) & 0xFF);
- if (ritorno==255)
- printf("Il figlio con pid=%d ha ritornato %d e quindi vuole dire che ci sono stati dei problemi\n", pid, ritorno);
- else printf("Il figlio con pid=%d ha ritornato %d\n", pid, ritorno);
- }
- }
- exit(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement