Advertisement
Vladpepe

Untitled

May 17th, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.02 KB | None | 0 0
  1. 13 GIUGNO 2018
  2. La parte in C accetta un numero variabile N+1 di parametri (con N maggiore o uguale a 2, da controllare) che
  3. rappresentano N nomi di file (F1, F2. ... FN-1), mentre l’ultimo rappresenta un numero intero strettamente positivo
  4. (Y) (da controllare) che indica la lunghezza in linee dei file: infatti, la lunghezza in linee dei file è la stessa (questo
  5. viene garantito dalla parte shell e NON deve essere controllato).
  6. 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 agli Nfile Ff (con f= i+1). Ogni processo figlio Pi deve leggere tutte le Y linee del file associato
  7. Ff calcolando la lunghezza di ogni linea, compreso il terminatore di linea. I processi figli e il processo padre
  8. devono attenersi a questo schema di comunicazione a pipeline: il figlio P0 comunica con il figlio P1 che
  9. comunica con il figlio P2 etc. fino al figlio PN-1 che comunica con il padre. Questo schema a pipeline deve
  10. prevedere l’invio in avanti, per ognuna delle Y linee dei file, di un array di strutture dati ognuna delle quali
  11. deve contenere due campi: 1) c1, di tipo int, che deve contenere il pid del processo figlio; 2) c2, di tipo int, che
  12. deve contenere la lunghezza della linea corrente, compreso il terminatore di linea. Gli array di strutture DEVONO
  13. essere creati da ogni figlio della dimensione minima necessaria per la comunicazione sia in ricezione che in
  14. spedizione. Quindi la comunicazione deve avvenire in particolare in questo modo: il figlio P0 passa in avanti (cioè
  15. comunica), per la prima linea, un array di strutture A1, che contiene una sola struttura con c1 uguale al suo pid e
  16. con c2 uguale alla lunghezza della prima linea (compreso il terminatore di linea) del file F1; il figlio seguente P1,
  17. dopo aver calcolato la lunghezza della sua prima linea (compreso il terminatore di linea) del file F2, deve leggere
  18. (con una singola read) l’array A1 inviato da P0 e quindi deve confezionare l’array A2 che corrisponde all’array
  19. A1 aggiungendo all’ultimo posto la struttura con i propri dati e la passa (con una singola write) al figlio seguente
  20. P2, etc. fino al figlio PN-1, che si comporta in modo analogo, ma passa al padre, e così via per ognuna delle
  21. altre linee. Quindi, al processo padre deve arrivare, per ognuna delle Y linee dei file, un array AN di N strutture
  22. (uno per ogni processo P0 … PN-1). Per ogni array AN ricevuto, il padre deve effettuare un ordinamento in senso
  23. crescente in base alle lunghezze e quindi deve riportare su standard output i dati così ordinati di ognuna delle N
  24. strutture insieme al numero di linea cui si riferisce l’array e ai file cui si riferiscono i dati.
  25. Al termine, ogni processo figlio Pi deve ritornare al padre il valore intero corrisponde al proprio indice d’ordine
  26. (i); il padre deve stampare su standard output il PID di ogni figlio e il valore ritornato.
  27.  
  28. /* Soluzione della parte C del compito del 13 Giugno 2018 */
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32. #include <sys/wait.h>
  33. #include <sys/stat.h>
  34. #include <string.h>
  35. #include <fcntl.h>
  36. #include <ctype.h>
  37.  
  38. typedef int pipe_t[2];
  39. typedef struct{
  40.         int pid;    /* pid figlio (campo c1 del testo) */
  41.     int lunghezza;  /* lunghezza linea (campo c2 del testo) */
  42.         } s;
  43.  
  44. typedef struct{
  45.         int pid;    /* pid figlio */
  46.     int indice; /* indice del figlio: CAMPO AGGIUNTO DAL PADRE */
  47.     int lunghezza;  /* lunghezza linea */
  48.         } s_padre;
  49.  
  50. void bubbleSort(s_padre v[],int dim) /* il tipo degli elementi NON e' un semplice int come riportato sul testo, ma deve essere il tipo s_padre (appositamente definito) */
  51. {
  52. int i;
  53. int ordinato=0;
  54. s_padre a;  /* variabile di appoggio per fare lo scambio */
  55.         while (dim>1 && ordinato!=1)
  56.         {
  57.                 ordinato=1;
  58.                 for (i=0;i<dim-1;i++)
  59.                 if (v[i].lunghezza > v[i+1].lunghezza) /* chiaramente il confronto va fatto sul campo lunghezza della struttura */
  60.                 {  /* viene effettuato in questo caso un ordinamento in senso crescente */
  61.                         /* scambio gli elementi */
  62.                         a=v[i];
  63.                         v[i]=v[i+1];
  64.                         v[i+1]=a;
  65.                         ordinato=0;
  66.                 }
  67.                 dim--;
  68.         }
  69. }/* fine bubblesort */
  70.  
  71. int main (int argc, char **argv)
  72. {
  73. int N;          /* numero di file */
  74. int Y;          /* numero di linee */
  75. int pid;        /* pid per fork */
  76. 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 */
  77. int i,j;        /* contatori */
  78. int fd;         /* file descriptor */
  79. int pidFiglio, status, ritorno; /* per valore di ritorno figli */
  80. char ch;        /* carattere letto da linea */
  81. s *cur;         /* array di strutture usate dai figli */
  82. s_padre *cur_padre;     /* array di strutture usate dal padre */
  83. int nr;         /* variabili per salvare valori di ritorno di read su pipe */
  84.  
  85. /* controllo sul numero di parametri almeno 2 file e un carattere */
  86. if (argc < 4)
  87. {
  88.     printf("Errore numero di parametri\n");
  89.     exit(1);
  90. }
  91.  
  92. /* calcoliamo valore di Y e lo controlliamo */
  93. Y=atoi(argv[argc-1]);
  94. if (Y < 0)
  95. {
  96.    printf("Errore valore di Y\n");
  97.    exit(2);
  98. }
  99.  
  100. /* stampa di debugging */
  101. printf("Valore di Y %d\n", Y);
  102.  
  103. N = argc-2;
  104. printf("Numero di processi da creare %d\n", N);
  105.  
  106. /* allocazione pipe */
  107. if ((pipes=(pipe_t *)malloc(N*sizeof(pipe_t))) == NULL)
  108. {
  109.     printf("Errore allocazione pipe\n");
  110.     exit(3);
  111. }
  112.  
  113. /* creazione pipe */
  114. for (i=0;i<N;i++)
  115.     if(pipe(pipes[i])<0)
  116.     {
  117.         printf("Errore creazione pipe\n");
  118.         exit(4);
  119.     }
  120.  
  121. /* creazione figli */
  122. for (i=0;i<N;i++)
  123. {
  124.     if ((pid=fork())<0)
  125.     {
  126.         printf("Errore creazione figli\n");
  127.         exit(5);
  128.     }
  129.     else if (pid==0)
  130.     {   /* codice figlio */
  131.         printf("Sono il figlio %d e sono associato al file %s\n", getpid(), argv[i+1]);
  132.         /* nel caso di errore in un figlio decidiamo di ritornare un valore via via crescente rispetto al massimo valore di i (cioe' N-1) */
  133.         /* chiusura pipes inutilizzate */
  134.         for (j=0;j<N;j++)
  135.         {
  136.             if (j!=i)
  137.                 close (pipes[j][1]);
  138.             if ((i == 0) || (j != i-1))
  139.                 close (pipes[j][0]);
  140.         }  
  141.  
  142.         /* allocazione dell'array di strutture specifico di questo figlio */
  143.         /* creiamo un array di dimensione i+1 anche se leggeremo i strutture, dato che poi ci servira' riempire la i+1-esima struttura! */
  144.         if ((cur=(s *)malloc((i+1)*sizeof(s))) == NULL)
  145.         {
  146.                 printf("Errore allocazione cur\n");
  147.                 exit(N);
  148.         }
  149.         /* inizializziamo l'ultima struttura che e' quella specifica del figlio corrente (nel caso del primo figlio sara' l'unica struttura */
  150.         cur[i].pid = getpid();
  151.         cur[i].lunghezza= 0;
  152.    
  153.         /* apertura file */
  154.         if ((fd=open(argv[i+1],O_RDONLY))<0)
  155.         {
  156.             printf("Impossibile aprire il file %s\n", argv[i+1]);
  157.             exit(N+1);
  158.         }
  159.         while(read(fd,&ch,1)>0)
  160.         {
  161.             /* se leggo un carattere, incremento la lunghezza della linea */
  162.             cur[i].lunghezza++;
  163.             if (ch == '\n')
  164.             {
  165.                 /* se siamo a fine linea si deve leggere dal figlio precedente l'array (se non siamo il primo figlio) e mandare la struttura al figlio successivo */
  166.                 if (i!=0)
  167.                 /* lettura da pipe dell'array di strutture per tutti i figli a parte il primo */
  168.                 {      
  169.                     nr=read(pipes[i-1][0],cur,i*sizeof(s));
  170.                     if (nr != i*sizeof(s))
  171.                         {  
  172.                             printf("Figlio %d ha letto un numero di strutture sbagliate %d\n", i, nr);
  173.                             exit(N+2);
  174.                         }  
  175.                     /*
  176.                     for(j=0;j<i;j++)
  177.                         printf("HO ricevuto da figlio di pid %d la lunghezza %d\n", cur[j].pid, cur[j].lunghezza);
  178.                     */
  179.                 }        
  180.  
  181.                 /* tutti i figli mandano in avanti, l'ultimo figlio manda al padre un array di strutture (i ricevute dal processo precedente e la i+1-esima la propria */
  182.                 write(pipes[i][1],cur,(i+1)*sizeof(s));
  183.                 cur[i].lunghezza= 0;    /* si deve azzerare nuovamente la lunghezza per la prossima linea */
  184.             }
  185.         }  
  186.         exit(i); /* ogni figlio deve ritornare al padre il proprio indice */
  187.     }
  188. } /* fine for */
  189.  
  190. /* codice del padre */
  191. /* chiusura pipe: tutte meno l'ultima in lettura */
  192. for (i=0;i<N;i++)
  193. {
  194.     close (pipes[i][1]);
  195.     if (i != N-1) close (pipes[i][0]);
  196. }
  197.  
  198. /* allocazione dell'array di strutture specifico per il padre per la read */
  199. /* creiamo un array di dimensione N quanto il numero di figli! */
  200. if ((cur=(s *)malloc(N*sizeof(s))) == NULL)
  201. {
  202.         printf("Errore allocazione cur nel padre\n");
  203.         exit(6);
  204. }
  205.  
  206. /* allocazione dell'array di strutture specifico per il padre per l'ordinamento */
  207. /* creiamo un array di dimensione N quanto il numero di figli! */
  208. if ((cur_padre=(s_padre *)malloc(N*sizeof(s_padre))) == NULL)
  209. {
  210.         printf("Errore allocazione curi_padre nel padre\n");
  211.         exit(7);
  212. }
  213.  
  214. /* il padre deve leggere via via gli array di strutture che gli arrivano dall'ultimo figlio: uno per ogni linea */
  215. for (j=1;j<=Y;j++)
  216. {
  217.     nr=read(pipes[N-1][0],cur,N*sizeof(s));
  218.     if (nr != N*sizeof(s))
  219.     {
  220.             printf("Padre ha letto un numero di strutture sbagliate %d\n", nr);
  221.             exit(8);
  222.     }
  223.     /* il padre deve copiare l'array ricevuto nel proprio array */
  224.     for (i=0;i<N;i++)
  225.     {
  226.         cur_padre[i].pid = cur[i].pid;
  227.         cur_padre[i].indice = i;
  228.         cur_padre[i].lunghezza = cur[i].lunghezza;
  229.     }
  230.     /* ordiniamo l'array cur_padre */
  231.     bubbleSort(cur_padre,N);
  232.     /* stampiamo le informazioni */
  233.     for (i=0;i<N;i++)
  234.         printf("Il figlio con pid %d per il file %s ha calcolato per la linea %d la lunghezza %d\n", cur_padre[i].pid, argv[cur_padre[i].indice + 1], j, cur_padre[i].lunghezza);
  235. }
  236.  
  237. /* Il padre aspetta i figli */
  238. for (i=0; i < N; i++)
  239. {
  240.         pidFiglio = wait(&status);
  241.         if (pidFiglio < 0)
  242.         {
  243.                 printf("Errore in wait\n");
  244.                 exit(9);
  245.         }
  246.  
  247.         if ((status & 0xFF) != 0)
  248.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  249.         else
  250.         {
  251.         ritorno=(int)((status >> 8) & 0xFF);
  252.                 printf("Il figlio con pid=%d ha ritornato %d\n", pidFiglio, ritorno);
  253.         }
  254. }
  255. exit(0);
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement