Advertisement
Vladpepe

Untitled

May 23rd, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.93 KB | None | 0 0
  1. La parte in C accetta un unico parametro che rappresenta il nome assoluto di un file (F) (senza bigogno di
  2. controlli sul fatto che sia assoluto).
  3. Il processo padre deve generare 26 processi figli (P0, P1, … P25) tanti quanti i caratteri dell’alfabeto inglese:
  4. tutti i processi figli Pi (con i che varia da 0 a 25) sono associati all’unico file F e ognuno dei processi figli è
  5. associato al carattere alfabetico minuscolo corrispondente (P0 è associato al carattere ‘a’ fino a P25 che è
  6. associato al carattere ‘z’). Ogni processo figlio Pi deve leggere i caratteri del file F cercando il carattere a lui
  7. associato Ci (per i=0, C0=‘a’, … per ii=25, C25=‘z’). I processi figli e il processo padre devono attenersi a
  8. questo schema di comunicazione a pipeline: il figlio P0 comunica con il figlio P1 che comunica con il figlio
  9. P2 etc. fino al figlio P25 che comunica con il padre. Questo schema a pipeline deve prevedere l’invio in avanti
  10. di un array di strutture dati ognuna delle quali deve contenere due campi: 1) v1, di tipo char, che deve
  11. contenere il carattere Ci; 2) v2, di tipo long int, che deve contenere il numero di occorrenze del carattere Ci,
  12. calcolate dal corrispondente processo. Ogni array di strutture utilizzato dai figli e dal padre deve avere
  13. dimensione fissa (26 elementi!). Quindi la comunicazione deve avvenire in particolare in questo modo: il figlio
  14. P0 passa in avanti (cioè comunica) un array di strutture A0 (di 26 elementi), che contiene una sola struttura
  15. significativa (nell’elemento di indice 0 dell’array A0) con v1 uguale a ‘a’ e con v2 uguale al numero di
  16. occorrenze del carattere ‘a’ trovate da P0 nel file F; il figlio seguente P1, dopo aver calcolato numero di
  17. occorrenze del carattere associato C1 nel file F, deve leggere (con una singola read) l’array A0 inviato da P0 e
  18. quindi deve confezionare l’array A1 che corrisponde all’array A0 aggiungendo nell’elemento di indice 1 la
  19. struttura con i propri dati e la passa (con una singola write) al figlio seguente P2, etc. fino al figlio P25, che si
  20. comporta in modo analogo, ma passa al padre. Quindi, al processo padre deve arrivare l’array A25. Il processo
  21. padre, dopo aver ordinato tale array A25 in senso crescente rispetto al campo v2, deve riportare i dati di ognuna
  22. delle 26 strutture su standard output insieme al pid e all’indice i del processo che ha generato tale struttura.
  23. Al termine, ogni processo figlio Pi deve ritornare al padre l’ultimo carattere letto dal file F; il padre deve
  24. stampare su standard output il PID di ogni figlio e il valore ritornato sia come carattere che come valore ASCII
  25. (in decimale).
  26.  
  27. /* soluzione che non ha bisogno di usare array dinamici dato che il numero di processi e' noto staticamente e pari al numero di lettere minuscole dell'alfabeto inglese (26 lettere) */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <fcntl.h>
  31. #include <unistd.h>
  32. #include <sys/wait.h>
  33. #include <string.h>
  34. #define N 26 /* numero di figli da creare: il valore e' COSTANTE! */
  35.  
  36. typedef int pipe_t[2];
  37.  
  38. /* struttura il cui primo campo rapprenta il carattere ed il cui secondo campo il numero di occorrenze di quel carattere trovate nel file */
  39. typedef struct {
  40.     char ch;    /* campo v1 del testo */
  41.     long int occ;   /* campo v2 del testo */
  42. } data;
  43.  
  44.  
  45. /* bubblesort che ordina l'array di strutture di tipo data passato (va ad ordinare in base ai valore del campo occ delle strutture facenti parte dell'array) */
  46. void bubbleSort(data *v, int dim)
  47. {
  48.     int i;
  49.     data tmp;
  50.     int ordinato = 0;
  51.     while(dim > 0 && !ordinato)
  52.     {
  53.         ordinato = 1;
  54.         for(i=0; i < dim-1; i++)
  55.         {
  56.             if(v[i].occ > v[i+1].occ)
  57.             {
  58.                 tmp = v[i];
  59.                 v[i] = v[i+1];
  60.                 v[i+1] = tmp;
  61.                 ordinato = 0;
  62.             }
  63.         }
  64.    
  65.         dim--;
  66.     }
  67.  
  68. }
  69.  
  70. int main(int argc, char **argv)
  71. {
  72.     int pid[N];             /* array STATICO di process identifier dei processi generati tramite fork */
  73.     int pidFiglio, status, ritorno; /* per valore di ritorno figli */
  74.     char c;             /* carattere letto dai figli */
  75.     pipe_t pipes[N];        /* array STATICO di pipe usate a pipeline da primo figlio, a secondo figlio .... ultimo figlio e poi a padre: ogni processo legge dalla pipe i-1 e scrive sulla pipe i */
  76.     int i, j;           /* variabili di supporto usate nei cicli for */
  77.     int fd;             /* file descritor del file aperto dai figli in lettura */
  78.     data d[N];          /* array STATICO di strutture che i figli si passano nella pipeline, fino al padre */
  79.     char curr_ch;           /* carattere da cercare */
  80.     long int curr_occ;      /* conteggio corrente */
  81.     int nr,nw;          /* variabili per salvare valori di ritorno di read e write da/su pipe */
  82.    
  83. if (argc != 2)
  84. {
  85.     printf("Numero di parametri errati: ci vuole solo il nome di un file\n");
  86.     exit(1);
  87. }
  88.  
  89. /* creazione delle 26 pipe per la comunicazione */
  90. for(i = 0; i < N; i++)
  91. {
  92.     if(pipe(pipes[i]) < 0)
  93.     {
  94.         printf("Errore nella creazione delle pipe\n");
  95.         exit(2);
  96.     }
  97. }
  98.  
  99. /* genero i 26 figli */
  100. for(i = 0; i < N; i++)
  101. {
  102.     if((pid[i] = fork()) < 0)
  103.     {
  104.         printf("Errore nella creazione di un figlio\n");
  105.         exit(3);
  106.     }
  107.  
  108.     if(pid[i] == 0)
  109.     {
  110.     /* codice del figlio */
  111.     /* inizializziamo le variabili per il figlio corrente */
  112.     curr_ch = 'a'+i;    /* ogni figlio deve essere associato ad una lettera dell'alfabeto inglese, iniziando dalla 'a' */
  113.     curr_occ = 0;
  114.     printf("Sono il figlio di indice %d e pid %d e sto per cercare il carattere %c\n", i, getpid(), curr_ch);  
  115.     /* chiusura pipes inutilizzate */
  116.     for (j=0;j<N;j++)
  117.     {
  118.         if (j!=i)
  119.             close (pipes[j][1]);
  120.         if ((i == 0) || (j != i-1))
  121.             close (pipes[j][0]);
  122.     }
  123.  
  124.     /* apro il file in sola lettura */
  125.     if((fd = open(argv[1], O_RDONLY)) < 0)
  126.     {
  127.         printf("Errore nella apertura del file\n");
  128.         /* dato che i figli devono tornare un carattere in condizioni di non errore, torniamo un valore minore di 0 se c'e' errore in apertura file */
  129.         exit(-1);
  130.     }
  131.            
  132.     while(read(fd, &c, 1))
  133.     {
  134.         if (c == curr_ch)
  135.             curr_occ++;
  136.     }
  137.     if (i != 0)
  138.     {
  139.     /* lettura da pipe dell'array di strutture per tutti i figli a parte il primo */
  140.         nr=read(pipes[i-1][0],d,sizeof(data)*N);
  141.         if (nr!=sizeof(data)*N)
  142.         {
  143.             printf("Errore in lettura da pipe[%d]\n", i);
  144.             /* torniamo un valore minore di 0 se c'e' stato un errore in lettura da pipe */
  145.             exit(-2);
  146.         }
  147.     }
  148.     /* inseriamo le informazioni del figlio corrente nella posizione giusta */
  149.     d[i].ch = curr_ch;
  150.     d[i].occ = curr_occ;
  151.         /* printf("Il figlio di indice %d e pid %d ha trovato %ld occorrenze del carattere %c\n", i, getpid(), d[i].occ, d[i].ch); */
  152.     /* inviamo le informazioni al figlio seguente/padre */
  153.     nw=write(pipes[i][1],d,sizeof(data)*N);
  154.     if (nw!=sizeof(data)*N)
  155.     {
  156.         printf("Errore in scrittura da pipe[%d]\n",i);
  157.         /* torniamo un valore minore di 0 dato che c'e' stato un errore in scrittura su pipe */
  158.         exit(-3);
  159.     }
  160.     /* torniamo l'ultimo carattere letto (che sara' uguale per tutti i figli) */
  161.     exit(c);
  162.     }
  163. } /* fine for */
  164.  
  165. /* codice del padre */
  166. /* chiusura pipe: tutte meno l'ultima in lettura */
  167. for(i=0;i<N;i++)
  168.     {
  169.         close (pipes[i][1]);
  170.         if (i != N-1) close (pipes[i][0]);
  171.     }
  172.  
  173. /* il padre deve leggere un solo array */
  174. nr=read(pipes[N-1][0],d,sizeof(data)*N);
  175. if (nr!=sizeof(data)*N)
  176. {
  177.     printf("Errore in lettura da pipe[N-1] per il padre\n");
  178.         exit(4);
  179. }
  180.  
  181. bubbleSort(d,N);
  182. for(i=0;i<N;i++)
  183. {
  184.     printf("Il figlio di indice %d e pid %d ha trovato %ld occorrenze del carattere %c\n", d[i].ch-'a', pid[(d[i].ch-'a')], d[i].occ, d[i].ch);
  185. }
  186.  
  187. /* Il padre aspetta i figli */
  188. for (i=0; i < N; i++)
  189. {
  190.         pidFiglio = wait(&status);
  191.         if (pidFiglio < 0)
  192.         {
  193.                 printf("Errore in wait\n");
  194.                 exit(5);
  195.         }
  196.  
  197.         if ((status & 0xFF) != 0)
  198.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  199.         else
  200.                 {
  201.             ritorno=(int)((status >> 8) & 0xFF);
  202.                     printf("Il figlio con pid=%d ha ritornato il carattere %c (in decimale %d)\n", pidFiglio, ritorno, ritorno);
  203.                 }
  204. }
  205.  
  206. exit(0);
  207. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement