Advertisement
Vladpepe

Untitled

May 17th, 2019
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.51 KB | None | 0 0
  1. 10 GIUGNO 2015
  2. La parte in C accetta un numero variabile N+1 di parametri (con N maggiore o uguale a 2) che
  3. rappresentano i primi N nomi di file (F0, F1, ... FN-1), mentre l’ultimo rappresenta un numero
  4. intero (H) strettamente positivo (da controllare) che indica la lunghezza in linee dei file: infatti, la
  5. lunghezza in linee dei file è la stessa (questo viene garantito dalla parte shell e NON deve essere
  6. controllato).
  7. Il processo padre deve, per prima cosa, chiedere all’utente un carattere Cx e quindi deve generare N
  8. processi figli (P0 … PN-1) ognuno dei quali è associato ad uno dei file Fi. Ogni processo figlio Pi
  9. deve leggere le linee del file associato Fi sempre fino alla fine. I processi figli e il processo padre
  10. devono attenersi a questo schema di comunicazione a pipeline: il figlio P0 comunica con il figlio
  11. P1 che comunica con il figlio P2 etc. fino al figlio PN-1 che comunica con il padre; questo schema
  12. a pipeline deve essere ripetuto H volte e cioè per ogni linea letta dai file associati Fi e deve
  13. prevedere l’invio in avanti, per ogni linea letta, via via di una struttura che deve contenere due
  14. campi, c1 e c2, con c1 uguale all’indice d’ordine di un processo e con c2 uguale al numero di
  15. occorrenze del carattere Cx nella linea corrente. In particolare, il figlio P0 passa in avanti (cioè
  16. comunica) per ogni linea letta via via una struttura S0, con c1 uguale a 0 e con c2 uguale al numero
  17. di occorrenze del carattere Cx nella linea corrente; il figlio seguente P1, dopo la lettura della
  18. propria linea corrente, confronta il numero di occorrenze del carattere Cx nella propria linea
  19. corrente con il valore ricevuto da P0 e se il proprio conteggio è minore confeziona la struttura S1
  20. con i propri dati e la passa al figlio seguente P2 altrimenti passa avanti la struttura S0 ricevuta, etc.
  21. fino al figlio PN-1, che si comporta in modo analogo, ma passa al padre. Quindi, al processo padre
  22. devono arrivare H strutture, una per ogni linea letta dai processi P0 … PN-1. Il padre per ogni linea
  23. riceve quindi l’informazione sia di quale figlio (in termini di indice) ha letto la linea con il numero
  24. di occorrenze minore per la linea corrente e sia del numero di tali occorrenze: il padre, deve
  25. riportare tale informazione su standard output insieme al numero d’ordine di linea cui si riferiscono
  26. e al pid del processo che ha trovato il numero di occorrenze minore.
  27. Al termine, ogni processo figlio Pi deve ritornare al padre il valore intero 0 se l’esecuzione è
  28. avvenuta con successo, altrimenti deve tornare un valore intero maggiore di 0 se ci sono stati dei
  29. problemi; il padre deve stampare su standard output il PID di ogni figlio e il valore ritornato.
  30.  
  31. /* Soluzione della parte C del compito del 10 Giugno 2015 */
  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.  
  40. typedef int pipe_t[2];
  41. typedef struct{
  42.         int id;     /* indice figlio (campo c1 del testo) */
  43.     int occ;    /* numero occorrenze (campo c2 del testo) */
  44.         } s_occ;
  45.  
  46. int main (int argc, char **argv)
  47. {
  48. int N;      /* numero di file */
  49. int H;      /* numero di linee */
  50. int *pid;   /* array di pid per fork */
  51. 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 */
  52. int i,j;    /* contatori */
  53. int fd;     /* file descriptor */
  54. int pidFiglio, status, ritorno; /* per valore di ritorno figli */
  55. char Cx, ch;    /* carattere da cercare e carattere letto da linea */
  56. s_occ cur;      /* struttura usata dal figlio corrente */
  57. s_occ pip;      /* struttura usata dal figlio e per la pipe */
  58. int nr,nw;      /* variabili per salvare valori di ritorno di read e write da/su pipe */
  59.  
  60. if (argc < 4)
  61. {
  62. printf("Errore numero di parametri\n");
  63. exit(1);
  64. }
  65.  
  66. H = atoi(argv[argc-1]);
  67. printf("Numero di linee %d\n", H);
  68. if (H < 0)
  69. {
  70.     printf("Errore numero linee: non strettamente maggiore di zero\n");
  71.     exit(2);
  72. }
  73.  
  74. N = argc-2;
  75. printf("Numero di processi da creare %d\n", N);
  76.  
  77. /* allocazione pid */
  78. if ((pid=(int *)malloc(N*sizeof(int))) == NULL)
  79. {
  80.     printf("Errore allocazione pid\n");
  81.     exit(3);
  82. }
  83.  
  84. /* allocazione pipe */
  85. if ((pipes=(pipe_t *)malloc(N*sizeof(pipe_t))) == NULL)
  86. {
  87.     printf("Errore allocazione pipe\n");
  88.     exit(4);
  89. }
  90.  
  91. /* creazione pipe */
  92. for (i=0;i<N;i++)
  93.     if(pipe(pipes[i])<0)
  94.     {
  95.         printf("Errore creazione pipe\n");
  96.         exit(5);
  97.     }
  98.  
  99. /* chiediamo all'utente per prima cosa un carattere Cx */
  100. printf("Inserire un carattere Cx che verra' cercato dai figli in ogni linea dei file associati\n");
  101. read(0, &Cx, 1);
  102. printf("Carattere letto %c\n", Cx);
  103.  
  104. /* creazione figli */
  105. for (i=0;i<N;i++)
  106. {
  107.     if ((pid[i]=fork())<0)
  108.     {
  109.         printf("Errore creazione figli\n");
  110.         exit(6);
  111.     }
  112.     else if (pid[i]==0)
  113.     { /* codice figlio */
  114.     printf("Sono il figlio %d\n", getpid());
  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.     /* inizializzazione struttura */
  125.     cur.id = i;
  126.     cur.occ= 0;
  127.     /* apertura file */
  128.     if ((fd=open(argv[i+1],O_RDONLY))<0)
  129.     {
  130.     printf("Impossibile aprire il file %s\n", argv[i+1]);
  131.     /* torniamo un valore maggiore di 0 dato che non siamo stati in grado di aprire il file */
  132.     exit(1);
  133.     }
  134.     while(read(fd,&ch,1)>0)
  135.     {
  136.         /* controllo carattere */
  137.         if (ch == Cx)
  138.             cur.occ++;
  139.         else
  140.             if (ch=='\n')
  141.             {      
  142.                 if (i!=0)
  143.                 {  
  144.                     /* lettura da pipe della struttura per tutti i figli a parte il primo */
  145.                     nr=read(pipes[i-1][0],&pip,sizeof(s_occ));
  146.                     if (nr!=sizeof(pip))
  147.                          {
  148.                             printf("Errore in lettura da pipe[%d]\n",i);
  149.                             /* torniamo un valore maggiore di 0 dato che c'e' stato un errore in lettura da pipe */
  150.                             exit(2);
  151.                          }
  152.                     else   
  153.                     if (cur.occ >= pip.occ)
  154.                     /* se il numero di occorrenze non e' minore dobbiamo passare avanti la struttura ricevuta
  155.                        altrimenti rimane valida la struttura corrente */
  156.                     {  
  157.                     cur.id = pip.id;
  158.                     cur.occ = pip.occ;
  159.                     }
  160.                 }
  161.                 /* comunicazione struttura al figlio seguente  */
  162.                 nw=write(pipes[i][1],&cur,sizeof(s_occ));
  163.                 if (nw!=sizeof(pip))
  164.                 {
  165.                     printf("Errore in scrittura da pipe[%d]\n",i);
  166.                     /* torniamo un valore maggiore di 0 dato che c'e' stato un errore in scrittura su pipe */
  167.                     exit(3);
  168.                 }
  169.                 else   
  170.                 {
  171.                     /* dopo l'invio ripristino dei dati */
  172.                     cur.occ=0;
  173.                     cur.id=i;
  174.                 }
  175.             }  
  176.         }  
  177.     exit(0);
  178.     }
  179. } /* fine for */
  180.  
  181. /* codice del padre */
  182. /* chiusura pipe: tutte meno l'ultima in lettura */
  183. for(i=0;i<N;i++)
  184.     {
  185.     close (pipes[i][1]);
  186.     if (i != N-1) close (pipes[i][0]);
  187.     }
  188.  
  189. /* il padre deve leggere H strutture, tante quante sono le linee lette dai figli */
  190. for(j=0;j<H;j++)
  191.     {
  192.     read(pipes[N-1][0],&pip,sizeof(s_occ));
  193.     printf("Ricevuto per la linea %d che il figlio di indice %d e pid %d ha trovato %d occorrenze del carattere %c\n", j, pip.id, pid[pip.id], pip.occ, Cx);
  194.     }
  195.  
  196. /* Il padre aspetta i figli */
  197. for (i=0; i < N; i++)
  198.         {
  199.         pidFiglio = wait(&status);
  200.         if (pidFiglio < 0)
  201.                 {
  202.                 printf("Errore in wait\n");
  203.                 exit (7);
  204.                 }
  205.  
  206.         if ((status & 0xFF) != 0)
  207.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  208.         else
  209.                 { ritorno=(int)((status >> 8) & 0xFF);
  210.                   printf("Il figlio con pid=%d ha ritornato %d\n", pidFiglio, ritorno);
  211.                 }
  212.         }
  213. return(0);
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement