Advertisement
Vladpepe

Untitled

May 17th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.07 KB | None | 0 0
  1. 1 GIUGNO 2018
  2. La parte in C accetta un numero variabile N+1 (con N maggiore o uguale a 2, da controllare) che
  3. rappresentano, i primi N, i nomi assoluti di file F1, F2, … FN-1 (con lunghezza in linee media uguale a
  4. K, da non controllare) mentre l’ultimo rappresenta un numero intero strettamente positivo (K, da
  5. controllare). Il processo padre deve innanzitutto chiedere all’utente di fornire un numero intero X
  6. strettamente positivo e minore o uguale a K e quindi deve generare N processi figli (P0 … PN-1): i
  7. processi figli Pi (con i che varia da 0 a N-1) sono associati agli N file Fa (con a= i+1). . Ogni processo
  8. figlio Pi deve leggere, dal suo file associato, la linea X-esima se esiste. Nel caso la linea esista, il processo
  9. figlio Pi, calcolata (come int) la lunghezza L di tale linea. compreso il terminatore di linea, deve mandare
  10. L al processo padre e quindi la linea (solo chiaramente i caratteri significativi della linea, compreso il
  11. terminatore di linea). Nel caso la linea NON esista, il processo figlio Pi, deve comunque mandare al
  12. processo padre una coppia di informazioni corrispondente ad L e linea con contenuti tali che il padre
  13. possa capire che la linea NON ESISTE! Il processo padre ha il compito di ricevere, rispettando l’ordine
  14. dei file, prima il valore intero L e quindi, usando in modo opportuno questa informazione, la linea: per
  15. ogni linea ricevuta, il processo padre deve riportare sullo standard output il pid del processo figlio che
  16. gli ha inviato le informazioni, il nome del file cui le informazioni si riferiscono e la linea.
  17. Al termine, ogni processo figlio Pi deve ritornare al padre il valore di L (supposto strettamente minore
  18. di 255) se la linea è stata trovata, altrimenti il valore 0. Il padre, dopo che i figli sono terminati, deve
  19. stampare, su standard output, i PID di ogni figlio con il corrispondente valore ritornato.
  20.  
  21.  
  22.  
  23.  
  24.  
  25. /* Soluzione della parte C del compito della II prova in itinere del 1 Giugno 2018 */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <fcntl.h>
  29. #include <unistd.h>
  30. #include <string.h>
  31. #include <sys/wait.h>
  32.  
  33. /* definiamo un tipo per un array di due interi */
  34. typedef int pipe_t[2];
  35.  
  36. int main(int argc,char **argv)
  37. {
  38. int *pid, pidFiglio;    /* array di pid per fork e pid per wait*/
  39. int N;          /* numero di file passati come parametri e numero di processi figli da creare */
  40. int K;          /* intero che rappresenta l'ultimo parametro passato */
  41. int X;          /* variabile che deve essere inserita da tastiera */
  42. int L;          /* lunghezza di ogni linea calcolata dai figli */
  43. int status, ritorno;    /* variabili di stato per le wait e per il ritorno del figlio */
  44. int trovata=0;      /* indica se e' stata trovata la linea indicata */
  45. int i,j;        /* indici per cicli */
  46. char linea[255];    /* array che serve per salvare la linea letta da ogni figlio, supposta non piu' lunga di 255 caratteri compreso il terminatore di linea (vedi commento riguardo a L nel testo) */
  47. int fd;         /* generico file descriptor */
  48. pipe_t *piped;      /* vettore dinamico per pipe figlio -> padre */
  49. int nr;         /* per controllare valore di ritorno della read da pipe */
  50.  
  51. /* controlliamo numero di parametri */
  52. /* devono esserci almeno tre parametri più argv[0] */
  53. if (argc < 4)
  54. {
  55.    printf("Errore nel numero di parametri: %d. Ci vuole almeno due nomi di file e un numero che rappresenta il numero medio di linee dei file!\n", argc);
  56.    exit(1);
  57. }
  58.  
  59. /* calcoliamo il numero di files passati */
  60. N=argc-2;
  61.  
  62. /* calcoliamo valore di K e lo controlliamo */
  63. K=atoi(argv[argc-1]);
  64. if (K < 0)
  65. {
  66.    printf("Errore valore di K\n");
  67.    exit(2);
  68. }
  69.  
  70. /* allocazione pid */
  71. if ((pid=(int *)malloc(N*sizeof(int))) == NULL)
  72. {
  73.         printf("Errore allocazione pid\n");
  74.         exit(3);
  75. }
  76.  
  77. /* allocazione dinamica pipe figli-padre */
  78. piped=(pipe_t *)malloc(sizeof(pipe_t)*N);
  79. if (piped == NULL)
  80. {
  81.    printf("Allocazione fallita pipe figli-padre\n");
  82.    exit(4);
  83. }
  84. /* creazione delle N pipe */
  85. for (i=0;i<N;i++)
  86. {
  87.    if (pipe(piped[i])!=0)
  88.    {
  89.       printf("Errore pipe\n");
  90.       exit(5);
  91.    }
  92. }
  93. /* chiediamo all'utente di inserire un numero X da tastiera */
  94. printf("Inserire un numero intero strettamente positivo X e minore o uguale a %d\n",K);
  95. scanf("%d",&X);
  96. /* controlliamo X */
  97. if (X <= 0 || X > K)
  98. {
  99.    printf("Il valore X inserito non e' valido\n");
  100.    exit(6);
  101. }
  102.  
  103. /* ciclo per la generazione degli N figli */
  104. for (i=0;i<N;i++)
  105. {
  106.    pid[i]=fork();
  107.    if (pid[i]<0)  /* errore */
  108.    {
  109.       printf("Errore fork\n");
  110.       exit(7);
  111.    }
  112.    if (pid[i]==0)  /* figlio i-esimo */
  113.    {
  114.       /* codice del figlio */
  115.       /* stampa di controllo */
  116.       printf("Figlio di indice %d e pid %d: selezionero' la linea %d-esima dal file %s\n",i,getpid(), X, argv[i+1]);
  117.       /* chiudo le pipe che non servono */
  118.       /* ogni figlio NON legge da nessuna pipe e scrive solo sulla propria piped[i] */
  119.       for (j=0;j<N;j++)
  120.       {
  121.          close(piped[j][0]);
  122.          if(j!=i)
  123.          {
  124.             close(piped[j][1]);
  125.          }
  126.       }
  127.  
  128.       /* apro il file di competenza, ossia quello di indice i+1 */
  129.       fd=open(argv[i+1],O_RDONLY);
  130.       if (fd < 0)
  131.       {
  132.          printf("Errore apertura file. Sono il figlio di indice %d\n",i);
  133.          exit(-1); /* in caso di errore decidiamo di tornare -1 che sara' interpretato come 255, che NON e' un valore accettabile per il padre */
  134.       }
  135.  
  136.       /* con un ciclo leggo la linea X-esima (se esiste) e ne calcolo la lunghezza */
  137.       L=0; /* valore iniziale dell'indice */
  138.       j=1; /* inizializzo il conteggio delle linee a 1 */
  139.       while (read(fd,&(linea[L]),1) != 0)
  140.       {
  141.         if (linea[L] == '\n')
  142.             {
  143.                     if (j == X) /* trovata la linea che dobbiamo selezionare e quindi la stampiamo dopo averla resa una stringa */
  144.             {
  145.                 /* printf("STAMPA DI DEBUGGING: La linea numero %d del file %s e':\n%s", j, argv[i+1], linea); */
  146.                 L++;    /* dobbiamo contare anche il terminatore di linea */
  147.                             trovata=1;
  148.                 ritorno=L;
  149.                 break; /* usciamo dal ciclo di lettura */
  150.             }          
  151.                     else
  152.                     {       L = 0; /* azzeriamo l'indice per la prossima linea */
  153.                             j++;    /* se troviamo un terminatore di linea incrementiamo il conteggio */
  154.                     }
  155.             }  
  156.             else L++;
  157.       }
  158.       if (!trovata)
  159.       {
  160.     /* se nel file non e' presente la linea X-esima dobbiamo mandare al padre comunque un valore di L e una 'linea': decidiamo di stabilire una frase che consenta al padre di capire che la linea non esiste */
  161.     sprintf(linea, "Il file %s non contiene la linea %d-esima\n", argv[i+1], X);
  162.     L = strlen(linea);
  163.     ritorno=0;
  164.       }
  165.       /* comunichiamo L al processo padre */
  166.       write(piped[i][1],&L,sizeof(L));
  167.       /* comunichiamo la linea al processo padre */
  168.       write(piped[i][1],linea, L);
  169.  
  170.       exit(ritorno);
  171.  
  172.       /* fine codice del figlio */
  173.    }
  174. }
  175. /* codice del padre */
  176. /* chiudo le pipe che non uso */
  177. for (i=0;i<N;i++)
  178. {
  179.    close(piped[i][1]);
  180. }
  181. /* riceviamo dai figli le lunghezze calcolate, in ordine di indice e quindi utilizzando queste lunghezze riceviamo le linee inviate dai figli */
  182. for (i=0;i<N;i++)
  183. {
  184.    nr=read(piped[i][0],&L,sizeof(int));
  185.    if (nr == 0)
  186.     printf("Il figlio con indice %d e pid %d ha avuto dei problemi\n",  i, pid[i]);
  187.    else
  188.    {
  189.    read(piped[i][0],linea,L);
  190.    /* il padre trasforma la linea ricevuta in una stringa in modo da non avere problemi: sovrascriviamo lo \n tanto nella printf seguente lo si aggiunge */
  191.    linea[L-1]='\0';
  192.    printf("Il figlio con indice %d e pid %d mi ha comunicato questo: %s\n", i, pid[i], linea);
  193.    }
  194. }
  195.  
  196. /* Attesa della terminazione dei figli */
  197. for(i=0;i<N;i++)
  198. {
  199.    pidFiglio = wait(&status);
  200.    if (pidFiglio < 0)
  201.    {
  202.       printf("Errore wait\n");
  203.       exit(8);
  204.    }
  205.    if ((status & 0xFF) != 0)
  206.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  207.    else
  208.    {
  209.                 ritorno=(int)((status >> 8) & 0xFF);
  210.                 printf("Il figlio con pid=%d ha ritornato %d\n", pidFiglio, ritorno);
  211.    }
  212. }
  213. exit(0);
  214. }/* fine del main */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement