Advertisement
Vladpepe

Untitled

May 23rd, 2019
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.51 KB | None | 0 0
  1. La parte in C accetta un numero variabile N di parametri (con N maggiore o uguale a 1, da
  2. controllare) che rappresentano N nomi di file (F1, F2, ... FN).
  3. Il processo padre deve generare N processi figli (P0, P1, … PN-1): i processi figli Pi (con i che
  4. varia da 0 a N-1) sono associati agli N file Fj (con j= i+1). Ogni processo figlio Pi deve leggere i
  5. caratteri del file associato Fj cercando la prima occorrenza (Cn) di un carattere numerico. I processi
  6. figli e il processo padre devono attenersi a questo schema di comunicazione a pipeline: il figlio P0
  7. comunica con il figlio P1 che comunica con il figlio P2 etc. fino al figlio PN-1 che comunica con il
  8. padre. Questo schema a pipeline deve prevedere l’invio in avanti di un singolo array di strutture
  9. dati, ognuna delle quali deve contenere due campi: 1) c1, di tipo int, che deve contenere l’indice
  10. d’ordine dei processi; 2) c2, (sempre) di tipo int, che deve contenere il numero corrispondente al
  11. carattere numerico Cn trovato dal corrispondente processo. Gli array di strutture DEVONO essere
  12. creati da ogni figlio della dimensione minima necessaria per la comunicazione sia in ricezione che
  13. in spedizione. Quindi la comunicazione deve avvenire in particolare in questo modo: il figlio P0,
  14. dopo aver trovato la prima occorrenza (Cn0) di un carattere numerico nel file F1, passa in avanti
  15. (cioè comunica) un array di strutture A1, che contiene una sola struttura con c1 uguale a 0 e con c2
  16. uguale al numero corrispondente al carattere Cn0 trovato da P0; il figlio seguente P1, dopo aver
  17. trovato la prima occorrenza (Cn1) di un carattere numerico nel file F2, deve leggere (con una
  18. singola read) l’array A1 inviato da P0 e quindi deve confezionare l’array A2 che corrisponde
  19. all’array A0 aggiungendo all’ultimo posto la struttura con i propri dati (c1 uguale a 1 e c2 uguale al
  20. numero corrispondete a Cn1) e la passa (con una singola write) al figlio seguente P2, etc. fino al
  21. figlio PN-1, che si comporta in modo analogo, ma passa al padre. Quindi, al processo padre deve
  22. arrivare l’array AN di N strutture (uno per ogni processo P0 … PN-1). Il padre deve riportare i dati
  23. di ognuna delle N strutture su standard output insieme al pid del processo corrispondente e inoltre
  24. deve calcolare, in termini di long int, la somma dei numeri comunicati dai figli, quindi la deve
  25. riportare su standard output.
  26. Al termine, ogni processo figlio Pi deve ritornare al padre il proprio carattere Cn; il padre deve
  27. stampare su standard output il PID di ogni figlio e il valore ritornato.
  28.  
  29. /* Soluzione della parte C del compito del 18 gennaio 2017 */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <sys/wait.h>
  34. #include <sys/stat.h>
  35. #include <string.h>
  36. #include <fcntl.h>
  37. #include <ctype.h>
  38.  
  39. typedef int pipe_t[2];
  40. typedef struct{
  41.         int id;     /* indice figlio (campo c1 del testo) */
  42.     int num;    /* numero corrispondente al carattere numerico (campo c2 del testo) */
  43.         } s;
  44.  
  45. int main (int argc, char **argv)
  46. {
  47. int N;              /* numero di file */
  48. int *pid;           /* array di pid per fork */
  49. pipe_t *pipes;          /* array 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 */
  50. int i,j;            /* contatori */
  51. int fd;             /* file descriptor */
  52. int pidFiglio, status, ritorno; /* per valore di ritorno figli */
  53. char Cn, ch;            /* carattere trovato e carattere letto */
  54. s *cur;             /* array di strutture usate dal figlio corrente */
  55. long int somma=0;       /* variabile per salvare la somma dei numeri comunicati dai figli */
  56. int nr;             /* variabile per salvare valori di ritorno di read su pipe */
  57.  
  58. /* controllo sul numero di parametri: almeno 1 file */
  59. if (argc < 2)
  60. {
  61. printf("Errore numero di parametri\n");
  62. exit(1);
  63. }
  64.  
  65. N = argc-1;
  66. printf("Numero di processi da creare %d\n", N);
  67.  
  68. /* allocazione pid */
  69. if ((pid=(int *)malloc(N*sizeof(int))) == NULL)
  70. {
  71.     printf("Errore allocazione pid\n");
  72.     exit(2);
  73. }
  74.  
  75. /* allocazione pipe */
  76. if ((pipes=(pipe_t *)malloc(N*sizeof(pipe_t))) == NULL)
  77. {
  78.     printf("Errore allocazione pipe\n");
  79.     exit(3);
  80. }
  81.  
  82. /* creazione pipe */
  83. for (i=0;i<N;i++)
  84.     if(pipe(pipes[i])<0)
  85.     {
  86.         printf("Errore creazione pipe\n");
  87.         exit(4);
  88.     }
  89.  
  90. /* creazione figli con salvataggio pid per fare in modo che il padre possa stampare i pid dei figli ricevendo il loro indice */
  91. for (i=0;i<N;i++)
  92. {
  93.     if ((pid[i]=fork())<0)
  94.     {
  95.         printf("Errore creazione figli\n");
  96.         exit(5);
  97.     }
  98.     else if (pid[i]==0)
  99.     { /* codice figlio */
  100.     printf("Sono il figlio %d\n", getpid());
  101.     /* nel caso di errore in un figlio decidiamo di ritornare il valore -1 che non puo' derivare dalla conversione di un carattere numerico */
  102.     /* chiusura pipes inutilizzate */
  103.     for (j=0;j<N;j++)
  104.     {
  105.         if (j!=i)
  106.             close (pipes[j][1]);
  107.         if ((i == 0) || (j != i-1))
  108.             close (pipes[j][0]);
  109.     }
  110.  
  111.     /* allocazione dell'array di strutture specifico di questo figlio */
  112.     /* creiamo un array di dimensione i+1 anche se leggeremo i strutture, dato che poi ci servira' riempire la i+1-esima struttura con le info del processo corrente! */
  113.     if ((cur=(s*)malloc((i+1)*sizeof(s))) == NULL)
  114.     {
  115.             printf("Errore allocazione cur\n");
  116.             exit(-1);
  117.     }
  118.     /* inizializziamo solo il primo campo dell'ultima struttura che e' quella specifica del figlio corrente (nel caso del primo figlio sara' l'unica struttura) */
  119.     cur[i].id = i;
  120.    
  121.     /* apertura file */
  122.     if ((fd=open(argv[i+1],O_RDONLY))<0)
  123.     {
  124.     printf("Impossibile aprire il file %s\n", argv[i+1]);
  125.     exit(-1);
  126.     }
  127.     while(read(fd,&ch,1) > 0)
  128.     {
  129.         /* cerco il primo carattere numerico */
  130.         if (isdigit(ch))
  131.         {
  132.         Cn=ch; /* non strettamente necessario, ma fatto per maggior leggibilita' */
  133.         cur[i].num=(int)(Cn-'0');
  134.          /*
  135.         printf("Sono il figlio di indice %d e pid %d e ho trovato il carattere %c\n", cur[i].id, getpid(), Cn);
  136.         */
  137.         break; /* al primo carattere numerico trovato smettiamo di leggere dal file */
  138.         }  
  139.     }
  140.     if (i != 0)
  141.     /* lettura da pipe dell'array di strutture per tutti i figli a parte il primo */
  142.  {      nr=read(pipes[i-1][0],cur,i*sizeof(s));
  143.         if (nr != i*sizeof(s))
  144.             {  
  145.             printf("Figlio %d ha letto un numero di strutture sbagliate %d\n", i, nr);
  146.             exit(-1);
  147.             }
  148.  /*
  149.         for(j=0;j<i;j++)
  150.         printf("Ho ricevuto da figlio di indice %d trovato il numero %d\n", cur[j].id, cur[j].num);
  151.   */
  152. }
  153.  
  154.     /* tutti i figli mandano in avanti, l'ultimo figlio manda al padre un array di strutture (i strutture ricevute dal processo precedente e la i+1-esima la propria) */
  155. /*
  156.     printf("Sto per mandare al figlio seguente %d strutture che sono: \n", i+1);
  157. for(j=0;j<i+1;j++)
  158.     printf("Sto per mandare processo %d trovato il numero %d\n", cur[j].id, cur[j].num);
  159. */
  160.         write(pipes[i][1],cur,(i+1)*sizeof(s));
  161.     /* si deve tornare il primo carattere numerico letto dal file */
  162.     exit(Cn);
  163.     }
  164. } /* fine for */
  165.  
  166. /* codice del padre */
  167. /* chiusura pipe: tutte meno l'ultima in lettura */
  168. for(i=0;i<N;i++)
  169.     {
  170.     close (pipes[i][1]);
  171.     if (i != N-1) close (pipes[i][0]);
  172.     }
  173. /* allocazione dell'array di strutture specifico per il padre */
  174. /* creiamo un array di dimensione N cioe' quanto il numero di figli! */
  175. if ((cur=(s*)malloc(N*sizeof(s))) == NULL)
  176.     {
  177.         printf("Errore allocazione cur nel padre\n");
  178.         exit(6);
  179.     }
  180.  
  181. /* il padre deve leggere l'array di strutture che gli arriva dall'ultimo figlio (con una unica read!) */
  182. nr=read(pipes[N-1][0],cur,N*sizeof(s));
  183. if (nr != N*sizeof(s))
  184.         {
  185.         printf("Padre ha letto un numero di strutture sbagliate %d\n", nr);
  186.         exit(7);
  187.         }
  188. printf("Padre ha letto un numero di strutture %d\n", N);
  189. /* il padre deve stampare i campi delle strutture ricevute, oltre che calcolare la somma dei numeri comunicati dai figli */
  190. for(i=0;i<N;i++)
  191.         {
  192.     printf("Il figlio di indice %d e pid %d ha trovato il numero %d\n", cur[i].id, pid[cur[i].id], cur[i].num);
  193.     somma=somma+(long int)cur[i].num;
  194.         }
  195. printf("La somma dei numeri comunicati dai figli e' %ld\n", somma);
  196.  
  197. /* Il padre aspetta i figli */
  198. for (i=0; i < N; i++)
  199.         {
  200.         pidFiglio = wait(&status);
  201.         if (pidFiglio < 0)
  202.                 {
  203.                 printf("Errore in wait\n");
  204.                 exit(8);
  205.                 }
  206.  
  207.         if ((status & 0xFF) != 0)
  208.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  209.         else
  210.                 { ritorno=(int)((status >> 8) & 0xFF);
  211.                   printf("Il figlio con pid=%d ha ritornato il carattere numerico %c\n", pidFiglio, ritorno);
  212.                 }
  213.         }
  214. return(0);
  215. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement