Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 11 LUGLIO 2018
- La parte in C accetta un numero variabile 1+N di parametri (con N maggiore o uguale a 2, da controllare) che
- rappresentano rispettivamente: il primo parametro un singolo carattere CZ (da controllare), mentre gli altri N nomi
- di file (F1, F2. ... FN-1).
- Il processo padre deve generare N processi figli (P0, P1, … PN-1): i processi figli Pi (con i che varia da 0 a N1) sono associati ai N file Ff (con f= i+2). Ogni processo figlio Pi deve leggere tutti i caratteri del file associato
- Ff cercando le occorrenze del carattere CZ; appena viene trovata una occorrenza del carattere CZ, il processo
- figlio Pi deve comunicare al padre la posizione di tale carattere (in termini di long int) e deve ricevere dal padre
- l’indicazione di stampare o meno su standard output delle informazioni (vedi dopo *). Il padre deve ricevere,
- rispettando l’ordine dei file Ff , da ogni figlio via via i valori long int che rappresentano la posizione all’interno
- del file della occorrenza corrente trovata. Quindi, al processo padre deve arrivare un insieme di valori long int
- (che via via potrebbe diminuire in quantità in dipendenza della terminazione dei figli): sicuramente il primo
- insieme (questo viene garantito dalla parte Shell) è costituito dalla prima posizione inviata dal figlio P0, dalla
- prima posizione inviata dal figlio P1, … , dalla prima posizione inviata dal figlio PN-1. Per ogni insieme ricevuto,
- il padre deve determinare il valore massimo e, SOLO AL PROCESSO FIGLIO CHE HA INVIATO TALE
- VALORE, deve indicare (*) di stampare su standard output il carattere trovato, assieme all’indice d’ordine del
- processo, il suo pid, la posizione e il nome del file associato, mentre a tutti gli altri processi figli deve indicare
- di non stampare1
- .
- Al termine, ogni processo figlio Pi deve ritornare al padre il numero di occorrenze trovate (supposto strettamente
- minore di 255) del carattere CZ; il padre deve stampare su standard output il PID di ogni figlio e il valore ritornato
- /* soluzione parte C esame del 11 Luglio 2018 */
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/wait.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- typedef int pipe_t[2]; /* tipo di dato per contenere i file descriptors di una pipe */
- /* VARIABILI GLOBALI */
- int *finito; /* array dinamico per indicare i figli che sono terminati */
- /* la semantica di questo array e' che ogni elemento vale 0 se il corrispondente processo NON e' finito, altrimenti vale 1 */
- int N; /* numero di processi figli */
- int finitof()
- {
- /* questa funzione verifica i valori memorizzati nell'array finito: appena trova un elemento uguale a 0 vuole dire che non tutti i processi figli sono finiti e quindi torna 0; tornera' 1 se e solo se tutti gli elementi dell'array sono a 1 e quindi tutti i processi sono finiti */
- int i;
- for (i=0; i < N; i++)
- if (!finito[i])
- /* appena ne trova uno che non ha finito */
- return 0; /* ritorna falso */
- return 1;
- }
- int main(int argc, char **argv)
- {
- int pid; /* variabile per fork */
- pipe_t *pipe_fp; /* array di pipe per la comunicazione figli-padre*/
- pipe_t *pipe_pf; /* array di pipe per l'indicazione padre-figli */
- char CZ; /* carattere da cercare */
- int fd; /* variabile per open */
- char ch; /* variabile per leggere dai file */
- char chControllo; /* variabile per inviare indicazione ai figli */
- long int posizione; /* QUESTA VARIABILE TIENE TRACCIA DELLA POSIZIONE NEL FILE, SENZA USARE LSEEK. La posizione del primo carattere e' assunta uguale a 0 */
- long int posizioneMax; /* usata dal padre per calcolare il massimo */
- int indice; /* usata dal padre per tenere traccia dell'indice del figlio che ha calcolato il massimo */
- int occorrenze; /* numero di occorrenze trovate che va ritornato al padre */
- int status, pidFiglio, ritorno; /* per wait */
- int i, j; /* indici per cicli */
- int nr, nw; /* per controlli read e write su/da pipe */
- if (argc < 4)
- {
- printf("Errore numero parametri %d\n", argc);
- exit(1);
- }
- /* Controlliamo se il primo parametro e' un singolo carattere */
- if (strlen(argv[1]) != 1)
- {
- printf("Errore primo parametro non singolo carattere %s\n", argv[1]);
- exit(2);
- }
- CZ = argv[1][0]; /* isoliamo il carattere che devono cercare i figli */
- printf("Carattere da cercare %c\n", CZ);
- N = argc - 2; /* ogni figlio e' associato a argv[2], argv[3]...argv[argc-1] */
- /* allocazione memoria dinamica per finito */
- finito = (int *) malloc(sizeof(int) * N);
- if(finito == NULL)
- {
- printf("Errore nella allocazione della memoria per array finito\n");
- exit(3);
- }
- /* ... e inizializzazione a 0: all'inizio nessun figlio e' finito */
- memset(finito, 0, N*sizeof(int));
- /* allocazione memoria dinamica per pipe_fp e pipe_pf */
- pipe_fp=malloc(N*sizeof(pipe_t));
- pipe_pf=malloc(N*sizeof(pipe_t));
- if ((pipe_fp == NULL) || (pipe_pf == NULL))
- {
- printf("Errore nelle malloc\n");
- exit(4);
- }
- /* creazione delle pipe */
- for (i=0; i < N; i++)
- {
- if (pipe(pipe_fp[i])!=0)
- {
- printf("Errore creazione delle pipe figli-padre\n");
- exit(5);
- }
- if (pipe(pipe_pf[i])!=0)
- {
- printf("Errore creazione delle pipe padre-figli\n");
- exit(6);
- }
- }
- /* creazione dei processi figli */
- for (i=0; i < N; i++)
- {
- pid=fork();
- if (pid < 0) /* errore */
- {
- printf("Errore nella fork con indice %d\n", i);
- exit(7);
- }
- if (pid == 0)
- {
- /* codice del figlio */
- /* stampa di debugging */
- printf("Figlio di indice %d e pid %d associato al file %s\n",i,getpid(), argv[i+2]);
- /* chiudiamo le pipe che non servono */
- /* ogni figlio scrive solo su pipe_fp[i] e legge solo da pipe_pf[i] */
- for (j=0;j<N;j++)
- {
- close(pipe_fp[j][0]);
- close(pipe_pf[j][1]);
- if (j!=i)
- {
- close(pipe_fp[j][1]);
- close(pipe_pf[j][0]);
- }
- }
- fd=open(argv[i+2], O_RDONLY);
- if (fd < 0)
- {
- printf("Impossibile aprire il file %s\n", argv[i+2]);
- exit(-1); /* in caso di errore torniamo -1 che verra' interpretato dal padre come 255 che non e' un valore accettabile */
- }
- /* inizializziamo sia posizione che occorrenze */
- posizione=0;
- occorrenze=0;
- while (read(fd, &ch, 1))
- {
- if (ch==CZ) /* se troviamo una occorrenza del carattere cercato */
- {
- occorrenze++; /* incrementiamo il numero di occorrenze */
- /* inviamo la posizione corrente al padre */
- nw=write(pipe_fp[i][1], &posizione, sizeof(posizione));
- if (nw != sizeof(posizione))
- {
- printf("Impossibile scrivere sulla pipe per il processo di indice %d\n", i);
- exit(-1);
- }
- /* aspettiamo dal padre se dobbiamo scrivere o meno */
- nr=read(pipe_pf[i][0], &chControllo, 1);
- if (nr != 1)
- {
- printf("Impossibile leggere dalla pipe per il processo di indice %d\n", i);
- exit(-1);
- }
- /* printf("FIGLIO indice %d ho ricevuto dal padre %c\n", i, chControllo); */
- if (chControllo =='S')
- {
- /* autorizzato, scriviamo */
- printf("Sono il figlio di indice %d e pid %d e ho trovato una occorrenza del carattere %c alla posizione %ld nel file %s\n", i, getpid(), CZ, posizione, argv[i+2]);
- }
- else
- { /* nulla, si continua a leggere */
- ;
- }
- }
- posizione++; /* incrementiamo il valore di posizione per il prossimo carattere */
- }
- exit(occorrenze); /* torniamo il numero di occorrenze trovate (supposto dal testo < di 255) */
- }
- }
- /*codice del padre*/
- /* chiudiamo le pipe che non usiamo */
- for (i=0;i<N;i++)
- {
- close(pipe_fp[i][1]);
- close(pipe_pf[i][0]);
- }
- /* continuiamo a ciclare su tutti i figli in ordine, finche' tutti non hanno finito */
- /* printf("PADRE valore della funzione finitof=%d\n", finitof()); */
- while(!finitof())
- {
- posizioneMax=-1; /* ATTENZIONE: il valore del massimo, va resettato per ogni insieme di valori letti dal padre */
- for (i=0; i < N; i++)
- {
- /* tentiamo di leggere la posizione dal figlio i-esimo: contestualmente viene aggiornato il valore del corrispondente elemento dell'array finito */
- finito[i] = (read(pipe_fp[i][0], &posizione, sizeof(posizione)) != sizeof(posizione)); /* nel caso la read torni un valore diverso da sizeof(posizione), il corrispondente valore di finito viene settato a 1 dato che la condizione e' vera! */
- /* printf("PADRE per indice %d ha calcolato finito = %d\n", i, finito[i]); */
- /* printf("PADRE per indice %d ha letto posizione = %ld\n", i, posizione); */
- if (!finito[i])
- {
- if (posizione > posizioneMax)
- {
- /* dobbiamo aggiornare il massimo */
- posizioneMax = posizione;
- /* debbiamo tenere conto dell'indice del processo che ha inviato il massimo */
- indice = i;
- }
- }
- /* else printf("PADRE il figlio di indice %d non ha inviato nulla\n", i); */
- }
- /* printf("PADRE ha calcolato posizioneMax=%ld e indice %d\n", posizioneMax, indice); */
- /* bisogna mandare ai figli l'indicazione giusta (S per scrivere, N per NON scrivere) */
- /* OSSERVAZIONE IMPORTANTE: IN QUESTA SOLUZIONE NON BASTA LA VARIABILE FINITO DATO CHE LA FASE DI SCRITTURA DEL PADRE AI FIGLI VIENE FATTA NEL CICLO FOR CHE SEGUE E QUINDI IL PADRE DEVE AVERE MODO DI FARE LA SCRITTURA SE E SOLO SE IL FIGLIO GLI HA INVIATO QUALCOSA E QUINDI NON E' FINITO, ALTRIMENTI (IN CASO DI ASSENZA DI QUESTO CONTROLLO) SE UN FIGLIO E' FINITO E IL PADRE GLI MANDA COMUNQUE IL CARATTERE DI CONTROLLO, IL PADRE RICEVEREBBE UN SEGNALE SIGPIPE E MORIREBBE (A MENO CHIARAMENTE DI NON GESTIRE QUESTO SEGNALE CON UNA FUNZIONE HANDLER SPECIFICA)! */
- for (i=0; i < N; i++)
- {
- if (i == indice) /* figlio che deve scrivere */
- chControllo = 'S';
- else chControllo = 'N';
- /* printf("PADRE per indice %d sta per mandare %c\n", i, chControllo); */
- if (!finito[i])
- {
- nw=write(pipe_pf[i][1], &chControllo, 1);
- if (nw != 1)
- printf("PADRE non e' riuscito ad inviare nulla al figlio di indice %d \n", i);
- }
- }
- /* printf("PADRE valore della funzione finitof=%d\n", finitof()); */
- }
- /* Attesa della terminazione dei figli */
- for(i=0;i<N;i++)
- {
- pidFiglio = wait(&status);
- if (pidFiglio < 0)
- {
- printf("Errore wait\n");
- exit(8);
- }
- 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 %d\n", pidFiglio, ritorno);
- }
- }
- exit(0);
- }/* fine del main */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement