Advertisement
Vladpepe

Untitled

May 17th, 2019
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.11 KB | None | 0 0
  1. 26 MAGGIO 2017
  2. La parte in C accetta un numero variabile N+1 di parametri (con N maggiore o uguale a 2, da
  3. controllare) che rappresentano i primi N nomi di file (F1, F2, ... FN) mentre l’ultimo rappresenta un
  4. singolo carattere (Cx) (da controllare).
  5. Il processo padre deve generare N processi figli (P0, P1, … PN-1): i processi figli Pi (con i che
  6. varia da 0 a N-1) sono associati agli N file Fk (con k= i+1). Ogni processo figlio Pi deve leggere i
  7. caratteri del file associato Fk calcolando (in termini di long int) le occorrenze del carattere Cx.
  8. Quindi, i processi figli e il processo padre devono attenersi a questo schema di comunicazione a
  9. pipeline: il figlio P0 comunica con il figlio P1 che comunica con il figlio P2 etc. fino al figlio PN-1
  10. che comunica con il padre. Questo schema a pipeline deve prevedere l’invio in avanti di una
  11. singola struttura dati, che deve contenere tre campi: 1) c1, di tipo long int, che deve contenere il
  12. valore massimo di occorrenze calcolato dal processo Pi; 2) c2, di tipo int, che deve contenere
  13. l’indice d’ordine (i) del processo che ha calcolato il massimo; 3) c3, di tipo long int, che deve
  14. contenere la somma di tutte le occorrenze calcolate dai processi. Quindi la comunicazione deve
  15. avvenire in particolare in questo modo: il figlio P0, dopo aver calcolato il numero di occorrenze
  16. occ0 del carattere Cx trovate nel file F1, passa in avanti (cioè comunica) (con una singola write) al
  17. processo P1 una struttura S0, con c1 uguale a occ0, c2 uguale a 0 e c3 uguale occ0; il figlio
  18. seguente P1, dopo aver calcolato il numero di occorrenze occ1 del carattere Cx trovate nel file F2,
  19. deve leggere (con una singola read) la struttura S0 inviata da P0 e quindi deve confezionare la
  20. struttura S1 con c1 uguale al massimo fra occ0 e occ1, c2 uguale all’indice del processo che ha
  21. calcolato il valore di c1 e c3 uguale alla somma di occ0 e occ1 e la passa (con una singola write) al
  22. figlio seguente P2, etc. fino al figlio PN-1, che si comporta in modo analogo, ma passa al padre.
  23. Quindi, al processo padre deve arrivare la struttura SN-1. Il padre deve riportare i dati di tale
  24. struttura su standard output insieme al pid del processo che ha calcolato il massimo numero di
  25. occorrenze e al nome del file in cui sono state trovate (inserendo opportune spiegazioni per
  26. l’utente).
  27. Al termine, ogni processo figlio Pi deve ritornare al padre il valore intero corrisponde al proprio
  28. indice d’ordine (i); il padre deve stampare su standard output il PID di ogni figlio e il valore
  29. ritornato.
  30.  
  31. /* Soluzione della parte C del compito della II prova in itinere del 26 Maggio 2017 */
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <unistd.h>
  35. #include <sys/wait.h>
  36. #include <sys/stat.h>
  37. #include <string.h>
  38. #include <fcntl.h>
  39. #include <ctype.h>
  40.  
  41. typedef int pipe_t[2];
  42. typedef struct{
  43.     long int occ;       /* numero massimo di occorrenze (campo c1 del testo) */
  44.         int id;         /* indice figlio (campo c2 del testo) */
  45.     long int somma;     /* somma del numero di occorrenze (campo c3 del testo) */
  46.         } s_occ;
  47.  
  48. int main (int argc, char **argv)
  49. {
  50. int N;          /* numero di file */
  51. int *pid;       /* array di pid per fork */
  52. pipe_t *pipes;      /* array di pipe usate a pipeline da primo figlio, a secondo figlio .... ultimo figlio e poi a padre: ogni processo (a parte il primo) legge dalla pipe i-1 e scrive sulla pipe i */
  53. int i,j;        /* indici */
  54. int fd;         /* file descriptor */
  55. int pidFiglio, status, ritorno; /* per valore di ritorno figli */
  56. char Cx, ch;        /* carattere da cercare e carattere letto da file */
  57. long int cur_occ;   /* conteggio delle occorrenze calcolate da ogni figlio */
  58. s_occ letta;        /* struttura usata dai figli e dal padre */
  59. int nr,nw;              /* variabili per salvare valori di ritorno di read/write da/su pipe */
  60.  
  61. /* controllo sul numero di parametri almeno 2 file e un carattere */
  62. if (argc < 4)
  63. {
  64.     printf("Errore numero di parametri\n");
  65.     exit(1);
  66. }
  67.  
  68. /* controlliamo che l'ultimo paramentro sia un singolo carattere */
  69. if (strlen(argv[argc-1]) != 1)
  70. {
  71.     printf("Errore ultimo parametro non singolo carattere\n");
  72.     exit(2);
  73. }
  74.  
  75. /* individuiamo il carattere da cercare */
  76. Cx = argv[argc-1][0];
  77. printf("Carattere da cercare %c\n", Cx);
  78.  
  79. N = argc-2;
  80. printf("Numero di processi da creare %d\n", N);
  81.  
  82. /* allocazione pid */
  83. if ((pid=(int *)malloc(N*sizeof(int))) == NULL)
  84. {
  85.     printf("Errore allocazione pid\n");
  86.     exit(3);
  87. }
  88.  
  89. /* allocazione pipe */
  90. if ((pipes=(pipe_t *)malloc(N*sizeof(pipe_t))) == NULL)
  91. {
  92.     printf("Errore allocazione pipe\n");
  93.     exit(4);
  94. }
  95.  
  96. /* creazione pipe */
  97. for (i=0;i<N;i++)
  98.     if(pipe(pipes[i])<0)
  99.     {
  100.         printf("Errore creazione pipe\n");
  101.         exit(5);
  102.     }
  103.  
  104. /* creazione figli */
  105. for (i=0;i<N;i++)
  106. {
  107.     if ((pid[i]=fork())<0)
  108.     {
  109.         printf("Errore creazione figlio\n");
  110.         exit(6);
  111.     }
  112.     else if (pid[i]==0)
  113.     { /* codice figlio */
  114.     printf("Sono il figlio %d\n", getpid());
  115.     /* nel caso di errore in un figlio decidiamo di ritornare un valore via via crescente rispetto al massimo valore di i (che e' N-1) */
  116.     /* chiusura pipes inutilizzate */
  117.     for (j=0;j<N;j++)
  118.     {
  119.         if (j!=i)
  120.             close (pipes[j][1]);
  121.         if ((i == 0) || (j != i-1))
  122.             close (pipes[j][0]);
  123.     }
  124.  
  125.     /* inizializziamo il contatore di occorrenze */
  126.     cur_occ= 0;
  127.    
  128.     /* apertura file */
  129.     if ((fd=open(argv[i+1],O_RDONLY))<0)
  130.     {
  131.         printf("Impossibile aprire il file %s\n", argv[i+1]);
  132.         exit(N);
  133.     }
  134.     while(read(fd,&ch,1)>0)
  135.     {
  136.         /* cerco il carattere */
  137.         if (ch == Cx)
  138.         {
  139.             cur_occ++;
  140.          /*
  141.         printf("Sono il figlio di indice %d e pid %d e ho trovato %ld occorrenze del carattere %c\n", i, getpid(), cur_occ, Cx);
  142.         */
  143.         }  
  144.     }
  145.     if (i == 0)
  146.     {  /* il figlio di indice 0 deve preparare la struttura da mandare al figlio seguente */
  147.         letta.id = 0;
  148.         letta.occ = cur_occ;
  149.         letta.somma = cur_occ;
  150.         }
  151.     else
  152.     {   nr=read(pipes[i-1][0],&letta,sizeof(s_occ));
  153.     /* lettura da pipe della struttura per tutti i figli a parte il primo */
  154.         if (nr != sizeof(s_occ))
  155.             {  
  156.                 printf("Figlio %d ha letto un numero di byte sbagliati %d\n", i, nr);
  157.                 exit(N+1);
  158.             }
  159.  /*
  160.         printf("HO ricevuto da figlio di indice %d che ha trovato %ld occorrenze del carattere %c\n", letta.id, letta.occ, Cx);
  161.   */
  162.         if (letta.occ < cur_occ)
  163.             {  /* il figlio di indice i ha calcolato un numero di occorrenze maggiore e quindi bisogna aggiornare i valori di letta */
  164.                 letta.id = i;
  165.                 letta.occ = cur_occ;
  166.             }  
  167.             /* il valore della somma, va aggiornato comunque */
  168.         letta.somma += cur_occ;
  169.     }
  170.     /* tutti i figli mandano in avanti, l'ultimo figlio manda al padre una struttura */
  171.     nw=write(pipes[i][1],&letta,sizeof(s_occ));
  172.     if (nw != sizeof(s_occ))
  173.         {
  174.                 printf("Figlio %d ha scritto un numero di byte sbagliati %d\n", i, nw);
  175.                 exit(N+2);
  176.         }
  177.     /* ogni figlio deve tornare il proprio indice d'ordine */
  178.     exit(i);
  179.     }
  180. } /* fine for */
  181.  
  182. /* codice del padre */
  183. /* chiusura pipe: tutte meno l'ultima in lettura */
  184. for(i=0;i<N;i++)
  185. {
  186.     close (pipes[i][1]);
  187.     if (i != N-1) close (pipes[i][0]);
  188. }
  189.  
  190. /* il padre deve leggere la struttura che gli arriva dall'ultimo figlio */
  191. nr=read(pipes[N-1][0],&letta,sizeof(s_occ));
  192. if (nr != sizeof(s_occ))
  193. {
  194.         printf("Padre ha letto un numero di byte sbagliati %d\n", nr);
  195.         exit(8);
  196. }
  197. /* il padre deve stampare i campi della struttura ricevuta */
  198. printf("Il figlio di indice %d e pid %d ha trovato il numero massimo di occorrenze %ld del carattere %c nel file %s\n", letta.id, pid[letta.id], letta.occ, Cx, argv[letta.id+1]);
  199. printf("I figli hanno trovato in totale %ld occorrenze del carattere %c nei file\n", letta.somma, Cx);
  200.  
  201. /* Il padre aspetta i figli */
  202. for (i=0; i < N; i++)
  203. {
  204.         pidFiglio = wait(&status);
  205.         if (pidFiglio < 0)
  206.         {
  207.                 printf("Errore in wait\n");
  208.                 exit(9);
  209.         }
  210.         if ((status & 0xFF) != 0)
  211.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  212.         else
  213.         {
  214.         ritorno=(int)((status >> 8) & 0xFF);
  215.             printf("Il figlio con pid=%d ha ritornato %d (se > di %d problemi)\n", pidFiglio, ritorno, N-1);
  216.         }
  217. }
  218. exit(0);
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement