Advertisement
Vladpepe

Untitled

May 17th, 2019
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.58 KB | None | 0 0
  1. 11 LUGLIO 2018
  2. La parte in C accetta un numero variabile 1+N di parametri (con N maggiore o uguale a 2, da controllare) che
  3. rappresentano rispettivamente: il primo parametro un singolo carattere CZ (da controllare), mentre gli altri N nomi
  4. di file (F1, F2. ... FN-1).
  5. 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
  6. Ff cercando le occorrenze del carattere CZ; appena viene trovata una occorrenza del carattere CZ, il processo
  7. figlio Pi deve comunicare al padre la posizione di tale carattere (in termini di long int) e deve ricevere dal padre
  8. l’indicazione di stampare o meno su standard output delle informazioni (vedi dopo *). Il padre deve ricevere,
  9. rispettando l’ordine dei file Ff , da ogni figlio via via i valori long int che rappresentano la posizione all’interno
  10. del file della occorrenza corrente trovata. Quindi, al processo padre deve arrivare un insieme di valori long int
  11. (che via via potrebbe diminuire in quantità in dipendenza della terminazione dei figli): sicuramente il primo
  12. insieme (questo viene garantito dalla parte Shell) è costituito dalla prima posizione inviata dal figlio P0, dalla
  13. prima posizione inviata dal figlio P1,, dalla prima posizione inviata dal figlio PN-1. Per ogni insieme ricevuto,
  14. il padre deve determinare il valore massimo e, SOLO AL PROCESSO FIGLIO CHE HA INVIATO TALE
  15. VALORE, deve indicare (*) di stampare su standard output il carattere trovato, assieme all’indice d’ordine del
  16. processo, il suo pid, la posizione e il nome del file associato, mentre a tutti gli altri processi figli deve indicare
  17. di non stampare1
  18. .
  19. Al termine, ogni processo figlio Pi deve ritornare al padre il numero di occorrenze trovate (supposto strettamente
  20. minore di 255) del carattere CZ; il padre deve stampare su standard output il PID di ogni figlio e il valore ritornato
  21.  
  22.  
  23. /* soluzione parte C esame del 11 Luglio 2018 */
  24. #include <stdio.h>
  25. #include <unistd.h>
  26. #include <stdlib.h>
  27. #include <sys/wait.h>
  28. #include <string.h>
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <fcntl.h>
  32.  
  33. typedef int pipe_t[2];      /* tipo di dato per contenere i file descriptors di una pipe */
  34.  
  35. /* VARIABILI GLOBALI */
  36. int *finito;    /* array dinamico per indicare i figli che sono terminati */
  37.         /* la semantica di questo array e' che ogni elemento vale 0 se il corrispondente processo NON e' finito, altrimenti vale 1 */
  38. int N;      /* numero di processi figli */
  39.  
  40. int finitof()
  41. {
  42. /* 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 */
  43.     int i;
  44.     for (i=0; i < N; i++)
  45.         if (!finito[i])
  46.             /* appena ne trova uno che non ha finito */
  47.             return 0; /* ritorna falso */
  48.     return 1;
  49. }
  50.  
  51. int main(int argc, char **argv)
  52. {
  53.     int pid;        /* variabile per fork */
  54.     pipe_t *pipe_fp;    /* array di pipe per la comunicazione figli-padre*/
  55.     pipe_t *pipe_pf;    /* array di pipe per l'indicazione padre-figli */
  56.     char CZ;        /* carattere da cercare */
  57.     int fd;         /* variabile per open */
  58.     char ch;        /* variabile per leggere dai file */
  59.     char chControllo;   /* variabile per inviare indicazione ai figli */
  60.     long int posizione;     /* QUESTA VARIABILE TIENE TRACCIA DELLA POSIZIONE NEL FILE, SENZA USARE LSEEK. La posizione del primo carattere e' assunta uguale a 0 */
  61.     long int posizioneMax;  /* usata dal padre per calcolare il massimo */
  62.     int indice;         /* usata dal padre per tenere traccia dell'indice del figlio che ha calcolato il massimo */
  63.     int occorrenze;     /* numero di occorrenze trovate che va ritornato al padre */
  64.     int status, pidFiglio, ritorno; /* per wait */
  65.     int i, j;       /* indici per cicli */
  66.     int nr, nw;     /* per controlli read e write su/da pipe */
  67.  
  68. if (argc < 4)
  69. {
  70.     printf("Errore numero parametri %d\n", argc);
  71.     exit(1);
  72. }
  73.  
  74. /* Controlliamo se il primo parametro e' un singolo carattere */
  75. if (strlen(argv[1]) != 1)
  76. {
  77.     printf("Errore primo parametro non singolo carattere %s\n", argv[1]);
  78.     exit(2);
  79. }
  80.  
  81. CZ = argv[1][0]; /* isoliamo il carattere che devono cercare i figli */
  82. printf("Carattere da cercare %c\n", CZ);
  83.  
  84. N = argc - 2; /* ogni figlio e' associato a argv[2], argv[3]...argv[argc-1] */
  85.  
  86. /* allocazione memoria dinamica per finito */
  87. finito = (int *) malloc(sizeof(int) * N);
  88. if(finito == NULL)
  89. {
  90.     printf("Errore nella allocazione della memoria per array finito\n");
  91.     exit(3);
  92. }
  93.    
  94. /* ... e inizializzazione a 0: all'inizio nessun figlio e' finito */
  95. memset(finito, 0, N*sizeof(int));
  96.  
  97. /* allocazione memoria dinamica per pipe_fp e pipe_pf */
  98. pipe_fp=malloc(N*sizeof(pipe_t));
  99. pipe_pf=malloc(N*sizeof(pipe_t));
  100. if ((pipe_fp == NULL) || (pipe_pf == NULL))
  101. {
  102.     printf("Errore nelle malloc\n");
  103.     exit(4);
  104. }
  105.  
  106. /* creazione delle pipe */
  107. for (i=0; i < N; i++)
  108. {
  109.     if (pipe(pipe_fp[i])!=0)
  110.     {
  111.         printf("Errore creazione delle pipe figli-padre\n");
  112.         exit(5);
  113.     }
  114.     if (pipe(pipe_pf[i])!=0)
  115.     {
  116.         printf("Errore creazione delle pipe padre-figli\n");
  117.         exit(6);
  118.     }
  119. }
  120.  
  121. /* creazione dei processi figli */
  122. for (i=0; i < N; i++)
  123. {
  124.     pid=fork();
  125.     if (pid < 0)  /* errore */
  126.     {
  127.         printf("Errore nella fork con indice %d\n", i);
  128.             exit(7);
  129.     }
  130.     if (pid == 0)
  131.     {
  132.         /* codice del figlio */
  133.         /* stampa di debugging */
  134.             printf("Figlio di indice %d e pid %d associato al file %s\n",i,getpid(), argv[i+2]);
  135.             /* chiudiamo le pipe che non servono */
  136.             /* ogni figlio scrive solo su pipe_fp[i] e legge solo da pipe_pf[i] */
  137.             for (j=0;j<N;j++)
  138.             {
  139.                 close(pipe_fp[j][0]);
  140.                 close(pipe_pf[j][1]);
  141.                 if (j!=i)
  142.                 {
  143.                     close(pipe_fp[j][1]);
  144.                     close(pipe_pf[j][0]);
  145.                 }
  146.             }
  147.  
  148.         fd=open(argv[i+2], O_RDONLY);
  149.         if (fd < 0)
  150.         {
  151.             printf("Impossibile aprire il file %s\n", argv[i+2]);
  152.             exit(-1); /* in caso di errore torniamo -1 che verra' interpretato dal padre come 255 che non e' un valore accettabile */
  153.         }
  154.  
  155.         /* inizializziamo sia posizione che occorrenze */
  156.         posizione=0;    
  157.         occorrenze=0;
  158.         while (read(fd, &ch, 1))
  159.         {
  160.             if (ch==CZ) /* se troviamo una occorrenza del carattere cercato */
  161.             {
  162.                 occorrenze++; /* incrementiamo il numero di occorrenze */
  163.                 /* inviamo la posizione corrente al padre */
  164.                 nw=write(pipe_fp[i][1], &posizione, sizeof(posizione));
  165.                 if (nw != sizeof(posizione))
  166.                     {      
  167.                                 printf("Impossibile scrivere sulla pipe per il processo di indice %d\n", i);
  168.                                 exit(-1);
  169.                         }
  170.                 /* aspettiamo dal padre se dobbiamo scrivere o meno */
  171.                 nr=read(pipe_pf[i][0], &chControllo, 1);
  172.                 if (nr != 1)
  173.                     {      
  174.                                 printf("Impossibile leggere dalla pipe per il processo di indice %d\n", i);
  175.                                 exit(-1);
  176.                     }      
  177.                 /* printf("FIGLIO indice %d ho ricevuto dal padre %c\n", i, chControllo); */
  178.                 if (chControllo =='S')
  179.                 {
  180.                     /* autorizzato, scriviamo */
  181.                     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]);
  182.                 }
  183.                 else
  184.                 {  /* nulla, si continua a leggere */
  185.                     ;
  186.                 }
  187.             }
  188.             posizione++;    /* incrementiamo il valore di posizione per il prossimo carattere */
  189.         }  
  190.         exit(occorrenze); /* torniamo il numero di occorrenze trovate (supposto dal testo < di 255) */
  191.     }
  192. }
  193.  
  194. /*codice del padre*/
  195. /* chiudiamo le pipe che non usiamo */
  196. for (i=0;i<N;i++)
  197. {
  198.    close(pipe_fp[i][1]);
  199.    close(pipe_pf[i][0]);
  200. }
  201.  
  202. /* continuiamo a ciclare su tutti i figli in ordine, finche' tutti non hanno finito */
  203. /* printf("PADRE valore della funzione finitof=%d\n", finitof()); */
  204. while(!finitof())
  205. {
  206.     posizioneMax=-1; /* ATTENZIONE: il valore del massimo, va resettato per ogni insieme di valori letti dal padre */
  207.     for (i=0; i < N; i++)
  208.     {
  209.         /* tentiamo di leggere la posizione dal figlio i-esimo: contestualmente viene aggiornato il valore del corrispondente elemento dell'array finito */
  210.         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! */
  211.         /* printf("PADRE per indice %d ha calcolato finito = %d\n", i, finito[i]); */
  212.         /* printf("PADRE per indice %d ha letto posizione = %ld\n", i, posizione); */
  213.  
  214.         if (!finito[i])
  215.         {
  216.             if (posizione > posizioneMax)
  217.             {
  218.                 /* dobbiamo aggiornare il massimo */
  219.                 posizioneMax = posizione;
  220.                 /* debbiamo tenere conto dell'indice del processo che ha inviato il massimo */
  221.                 indice = i;
  222.             }
  223.         }
  224.         /* else  printf("PADRE il figlio di indice %d non ha inviato nulla\n", i); */
  225.     }
  226.     /* printf("PADRE ha calcolato posizioneMax=%ld e indice %d\n", posizioneMax, indice); */
  227.     /* bisogna mandare ai figli l'indicazione giusta (S per scrivere, N per NON scrivere) */
  228.     /* 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)! */
  229.     for (i=0; i < N; i++)
  230.     {
  231.         if (i == indice) /* figlio che deve scrivere */
  232.             chControllo = 'S';
  233.         else chControllo = 'N';
  234.         /* printf("PADRE per indice %d sta per mandare %c\n", i, chControllo); */
  235.         if (!finito[i])
  236.         {
  237.             nw=write(pipe_pf[i][1], &chControllo, 1);
  238.             if (nw != 1)
  239.                 printf("PADRE non e' riuscito ad inviare nulla al figlio di indice %d \n", i);
  240.        
  241.         }
  242.     }
  243. /* printf("PADRE valore della funzione finitof=%d\n", finitof()); */
  244. }
  245.  
  246. /* Attesa della terminazione dei figli */
  247. for(i=0;i<N;i++)
  248. {
  249.    pidFiglio = wait(&status);
  250.    if (pidFiglio < 0)
  251.    {
  252.       printf("Errore wait\n");
  253.       exit(8);
  254.    }
  255.    if ((status & 0xFF) != 0)
  256.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  257.    else
  258.    {
  259.                 ritorno=(int)((status >> 8) & 0xFF);
  260.                 printf("Il figlio con pid=%d ha ritornato %d\n", pidFiglio, ritorno);
  261.    }
  262. }
  263. exit(0);
  264. }/* fine del main */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement