Advertisement
Vladpepe

Untitled

May 23rd, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.57 KB | None | 0 0
  1. La parte in C accetta un numero variabile pari N+1 di parametri maggiore o uguale a 2 (da controllare) che
  2. rappresentano, i primi N, i nomi assoluti di file F1, F2, … FN-1 (tutti con lunghezza in linee maggiore o uguale
  3. a K, che non deve essere controllata) mentre l’ultimo rappresenta un numero intero strettamente positivo (K, da
  4. controllare). Il processo padre deve innanzitutto chiedere all’utente di fornire un numero intero X strettamente
  5. positivo e minore o uguale a K e quindi deve generare N processi figli (P0 … PN-1): ogni processo figlio Pi è
  6. associato al file Fi. Ogni processo figlio Pi deve leggere, dal suo file associato, la linea X-esima e, calcolata
  7. (come int) la sua lunghezza L compreso il terminatore di linea, deve mandare L al processo padre. Il processo
  8. padre ha il compito di ricevere, rispettando l’ordine dei file, i valori interi che rappresentano le lunghezze L
  9. delle linee X-esime dei file. Il processo padre, dopo aver ordinato tali valori in senso crescente, deve comunicare
  10. ai vari figli Pi di riportare la linea X-esima sullo standard output: l’ordine di tali comunicazioni deve essere tale
  11. per cui vengano stampate prima le linee di maggiore lunghezza secondo l’ordinamento ottenuto; inoltre, prima
  12. di inoltrare tale comunicazione, il padre deve riportare sullo standard output il nome del file cui la linea Xesima si riferisce e la sua lunghezza L.
  13. Al termine, ogni processo figlio Pi deve ritornare al padre il valore risultante dal resto della divisione intera fra
  14. L e 255. Il padre, dopo che i figli sono terminati, deve stampare, su standard output, i PID di ogni figlio con il
  15. corrispondente valore ritornato.
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <fcntl.h>
  20. #include <unistd.h>
  21. #include <string.h>
  22. #include <sys/wait.h>
  23.  
  24. /* definiamo un tipo per un array di due interi */
  25. typedef int pipe_t[2];
  26. /* creiamo questa struttura in modo che il padre salvi oltre alla lunghezza della linea anche l'indice del figlio che l'ha mandata */
  27. /* NOTA BENE: NON VIENE USATA QUESTA STRUTTURA PER LA COMUNICAZIONE! */
  28. typedef struct{
  29.    int len;
  30.    int indice;
  31. }strutt;
  32.  
  33. void bubbleSort(strutt v[],int dim) /* il tipo degli elementi NON e' un semplice int come riportato sul testo, ma deve essere il tipo strutt (appositamente definito) */
  34. {
  35. int i;
  36. int ordinato=0;
  37. strutt a;  /* variabile di appoggio per fare lo scambio */
  38.     while (dim>1 && ordinato!=1)
  39.     {
  40.         ordinato=1;
  41.         for (i=0;i<dim-1;i++)
  42.             if (v[i].len > v[i+1].len) /* chiaramente il confronto va fatto sul campo len della struttura */
  43.             {  /* viene effettuato in questo caso un ordinamento in senso crescente */
  44.                 /* scambio gli elementi */
  45.                 a=v[i];
  46.                 v[i]=v[i+1];
  47.                 v[i+1]=a;
  48.                 ordinato=0;
  49.             }
  50.         dim--;
  51.     }  
  52. }/* fine bubblesort */
  53.  
  54. int main(int argc,char **argv)
  55. {
  56. int pid, pidFiglio;     /* pid per le fork e la wait*/
  57. int N;          /* numero di file passati come parametri e numero di processi figli da creare */
  58. int K;          /* intero che rappresenta l'ultimo parametro passato */
  59. int X;          /* valore intero che deve essere inserito da tastiera */
  60. int L;          /* lunghezza di ogni linea calcolata dai figli */
  61. int status, ritorno;    /* variabili di stato per le wait */
  62. int i,j;        /* indici per cicli */
  63. int retval;         /* variabile di ritorno dei figli */
  64. char linea[512];    /* array che serve per salvare la linea letta da ogni figlio, supposta non piu' lunga di 512 caratteri compreso il terminatore di linea */
  65. int fd;         /* generico file descriptor */
  66. strutt *vettore;    /* vettore dinamico dove il padre salva le lunghezze ricevute dagli N figli ed i loro indici */
  67. pipe_t *pfds_p;     /* vettore dinamico per pipe padre -> figlio */
  68. pipe_t *pfds_f;     /* vettore dinamico per pipe figlio -> padre */
  69.             /* N.B. servono 2*N pipe */
  70.  
  71. /* controlliamo il numero di parametri */
  72. /* devono esserci almeno due parametri più argv[0] */
  73. if (argc < 3)
  74. {
  75.    printf("Errore nel numero di parametri: %d\n", argc);
  76.    exit(1);
  77. }
  78.  
  79. /* calcoliamo il numero di file passati */
  80. N=argc-2;
  81.  
  82. /* calcoliamo valore di K e lo controlliamo */
  83. K=atoi(argv[argc-1]);
  84. if (K < 0)
  85. {
  86.    printf("Errore valore di K\n");
  87.    exit(2);
  88. }
  89. /* allocazione dinamica del vettore di lunghezze prima descritto */
  90. vettore=(strutt *)malloc(sizeof(strutt)*N);
  91. if (vettore == NULL)
  92. {
  93.    printf("allocazione fallita vettore delle lunghezze\n");
  94.    exit(3);
  95. }
  96. /* allocazione del vettore dinamico per le pipe padre-figli */
  97. pfds_p=(pipe_t *)malloc(sizeof(pipe_t)*N);
  98. if (pfds_p == NULL)
  99. {
  100.    printf("Allocazione fallita pipe padre-figli\n");
  101.    exit(4);
  102. }
  103. /* allocazione dinamica pipe figli-padre */
  104. pfds_f=(pipe_t *)malloc(sizeof(pipe_t)*N);
  105. if (pfds_f == NULL)
  106. {
  107.    printf("Allocazione fallita pipe figli-padre\n");
  108.    exit(5);
  109. }
  110. /* creazione delle 2 * N pipe */
  111. for (i=0;i<N;i++)
  112. {
  113.    if (pipe(pfds_p[i])!=0 || pipe(pfds_f[i])!=0)
  114.    {
  115.       printf("Errore pipe\n");
  116.       exit(6);
  117.    }
  118. }
  119. /* chiediamo all'utente di inserire un numero X da tastiera */
  120. printf("Inserire un numero intero strettamente positivo X e minore o uguale a %d\n",K);
  121. scanf("%d",&X); /* lo leggiamo con la scanf che e' la cosa piu' semplice */
  122. /* controlliamo X */
  123. if (X<=0 || X>K)
  124. {
  125.    printf("Il valore X inserito non e' valido\n");
  126.    exit(7);
  127. }
  128.  
  129. /* ciclo per la generazione degli N figli */
  130. for (i=0;i<N;i++)
  131. {
  132.    pid=fork();
  133.    if (pid < 0)  /* errore */
  134.    {
  135.       printf("Errore fork\n");
  136.       exit(8);
  137.    }
  138.    if (pid == 0)  /* figlio i-esimo */
  139.    {
  140.       /* codice del figlio */
  141.       /* stampa di debugging */
  142.       printf("Figlio di indice %d e pid %d: selezionero' la linea %d-esima dal file %s\n",i,getpid(), X, argv[i+1]);
  143.       /* chiudo le pipe che non servono */
  144.       /* ogni figlio legge solo da pfds_p e scrive solo su pfds_f */
  145.       for (j=0;j<N;j++)
  146.       {
  147.          close(pfds_p[j][1]);
  148.          close(pfds_f[j][0]);
  149.          if(j!=i)
  150.          {
  151.             close(pfds_p[j][0]);
  152.             close(pfds_f[j][1]);
  153.          }
  154.       }
  155.  
  156.       /* apro il file associatoa, ossia quello di indice i+1 */
  157.       fd=open(argv[i+1],O_RDONLY);
  158.       if (fd < 0)
  159.       {
  160.          printf("Errore apertura file. Sono il figlio di indice %d\n",i);
  161.          exit(-1); /* in caso di errore decidiamo di tornare -1 che sara' interpretato come 255 */
  162.       }
  163.  
  164.       /* con un ciclo leggo la linea X-esima e ne calcolo la lunghezza */
  165.       L=0; /* valore iniziale dell'indice */
  166.       j=1; /* inizializzo il conteggio delle linee a 1 */
  167.       while(read(fd,&(linea[L]),1) != 0)
  168.       {
  169.         if (linea[L] == '\n')
  170.             {
  171.                     if (j == X) /* trovata la linea che dobbiamo selezionare */
  172.             {
  173.                 /* printf("STAMPA DI DEBUGGING: La linea numero %d del file %s e':\n%s", j, argv[i+1], linea); */
  174.                             break; /* usciamo dal ciclo di lettura */
  175.             }          
  176.                     else
  177.                     {       L = 0; /* azzeriamo l'indice per la prossima linea */
  178.                             j++;    /* se troviamo un terminatore di linea incrementiamo il conteggio */
  179.                     }
  180.             }  
  181.             else L++;
  182.       }
  183.       L++; /* incrementiamo L per tenere conto anche del terminatore di linea */
  184.       /* comunichiamo L al processo padre */
  185.       write(pfds_f[i][1],&L,sizeof(L));
  186.  
  187.       /* si deve aspettare la comunicazione del padre prima di stampare la linea X-esima su stdout */
  188.       read(pfds_p[i][0],&L,sizeof(L)); /* dato che questa read e' solo di sincronizzazione il padre puo' mandare qualunque valore: decidiamo che il padre, reinvii indietro la lunghezza della linea */
  189.       write(1, linea, L);
  190.  
  191.       retval=(L%255); /* il valore di ritorno dei figli deve essere il resto della divisione intera di L con 255 (sicuramente un valore minore di 255) */
  192.       exit(retval);
  193.  
  194.       /* fine codice del figlio */
  195.    }
  196. }
  197. /* codice del padre */
  198. /* chiudo le pipe che il padre non usa */
  199. for (i=0;i<N;i++)
  200. {
  201.    close(pfds_f[i][1]);
  202.    close(pfds_p[i][0]);
  203. }
  204. /* riceviamo dai figli le lunghezze calcolate, in ordine di indice */
  205. for (i=0;i<N;i++)
  206. {
  207.    read(pfds_f[i][0],&(vettore[i].len),sizeof(int));
  208.    /* printf("STAMPA DI DEBUGGING: padre letto lunghezza %d dal figlio di indice %d\n", vettore[i].len, i);  */
  209.    vettore[i].indice=i; /* inseriamo anche l'indice del processo figlio da cui e' stata ricevuta la lunghezza */
  210. }
  211.  
  212. /* printf("STAMPA DI DEBUGGING: padre sta per ordinare il vettore\n"); */
  213.  
  214. /* ordiniamo il vettore in modo crescente */
  215. bubbleSort(vettore,N);
  216. /* printf("STAMPA DI DEBUGGING: padre ha ordinato il vettore\n");*/
  217.  
  218. /* comunichiamo ai figli di stampare la linea X-esima */
  219. /* scorro il vettore ordinato e comunico con il figlio: deciso di comunicare di nuovo la lunghezza al figlio per fargli capire che può procedere */
  220. /* scrivo sulla pipe corrispondente all'indice salvato nel vettore */
  221. for (i=0;i<N;i++)
  222. {  
  223.    /* printf("STAMPA DI DEBUGGING: Nome file: %s, lunghezza: %d\n",argv[(vettore[i].indice+1)],vettore[i].len); */
  224.    write(pfds_p[vettore[i].indice][1],&(vettore[i].len),sizeof(int));
  225.    sleep(1); /* introduciamo un leggero ritardo in modo da avere la stampa corretta da parte dei figli */
  226. }
  227.  
  228. /* Attesa della terminazione dei figli */
  229. for (i=0;i<N;i++)
  230. {
  231.    pidFiglio = wait(&status);
  232.    if (pidFiglio < 0)
  233.    {
  234.       printf("Errore wait\n");
  235.       exit(9);
  236.    }
  237.    if ((status & 0xFF) != 0)
  238.                 printf("Figlio con pid %d terminato in modo anomalo\n", pidFiglio);
  239.    else
  240.    {
  241.                 ritorno=(int)((status >> 8) & 0xFF);
  242.                 printf("Il figlio con pid=%d ha ritornato %d\n", pidFiglio, ritorno);
  243.    }
  244. }
  245. exit(0);
  246. }/* fine del main */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement