Vladpepe

Untitled

May 23rd, 2019
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.65 KB | None | 0 0
  1. La parte in C accetta un numero variabile N di parametri che rappresentano nomi di file (F0, F1, ... FN-1).
  2. Il processo padre deve generare N processi figli Pi (P0 … PN-1): ogni processo figlio è associato al corrispondente file
  3. Fi. Ognuno di tali processi figli deve creare a sua volta un processo nipote PPi (PP0 … PPN-1) associato sempre al
  4. corrispondente file Fi. Ogni processo figlio Pi e ogni nipote PPi esegue concorrentemente andando a cercare nel file
  5. associato Fi tutte le occorrenze dei caratteri alfabetici maiuscolo per il figlio e tutte le occorrenze dei caratteri numerici
  6. per il nipote. Ognuno dei processi figlio e nipote deve operare una modifica del file Fi: in specifico, ogni figlio deve
  7. trasformare ogni carattere alfabetico maiuscolo nel corrispondente carattere alfabetico minuscolo, mentre ogni nipote
  8. deve trasformare ogni carattere numerico nel carattere spazio. Una volta terminate le trasformazioni, sia i processi figli
  9. Pi che i processi nipoti PPi devono comunicare al padre il numero (in termini di long int) di trasformazioni effettuate.
  10. Il padre ha il compito di stampare su standard output, rispettando l'ordine dei file, il numero di trasformazioni ricevute
  11. da ogni figlio Pi e da ogni nipote PPi, riportando opportuni commenti esplicativi: ad esempio “nel file F0 sono stati
  12. trasformati tot1 caratteri alfabetici maiuscolo in caratteri alfabetici minuscolo e tot2 caratteri numerici nel carattere
  13. spazio”.
  14. Al termine, ogni processo nipote PPi deve ritornare al figlio Pi un opportuno codice ed analogamente ogni processo
  15. figlio Pi deve ritornare al padre un opportuno codice; il codice che ogni nipote PPi e ogni figlio Pi deve ritornare è:
  16. a) 0 se il numero di trasformazioni attuate è minore di 256;
  17. b) 1 se il numero di trasformazioni attuate è maggiore o uguale a 256, ma minore di 512;
  18. c) 2 se il numero di trasformazioni attuate è maggiore o uguale a 512, ma minore di 768;
  19. d) etc.
  20. Sia ogni figlio Pi e sia il padre devono stampare su standard output il PID di ogni nipote/figlio e il valore ritornato.
  21.  
  22. /* Soluzione della Prova d'esame del 14 Settembre 2011 - Parte C */
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <fcntl.h>
  26. #include <sys/stat.h>
  27. #include <unistd.h>
  28. #include <stdlib.h>
  29. #include <sys/wait.h>
  30. #include <ctype.h>
  31.  
  32. typedef int pipe_t[2];
  33.  
  34. int main(int argc, char **argv)
  35. {
  36.     /* -------- Variabili locali ---------- */
  37.     int pid;            /* process identifier per le fork() */
  38.     int N;              /* numero di file passati sulla riga di comando */
  39.     int status;         /* variabile di stato per la wait */
  40.     pipe_t *pipedFP;        /* array dinamico di pipe descriptors per comunicazioni figli-padre  */
  41.     pipe_t *pipedNP;        /* array dinamico di pipe descriptors per comunicazioni nipoti-padre  */
  42.     int fd;             /* file descriptor che serva sia ai figli che ai nipoti */
  43.     int i, j;           /* indici per i cicli */
  44.     char ch;            /* variabile che serve per leggere i caratteri sia da parte dei figli che dei nipoti */
  45.     long int trasformazioni=0;  /* variabile che mantiene il numero delle trasformazioni effettuate sia dai figli che dai nipoti */
  46.     int ritorno;            /* variabile che viene ritornata da ogni figlio al padre e da ogni nipote al figlio */
  47.     /* ------------------------------------ */
  48.    
  49.     /* Controllo sul numero di parametri (anche se non richiesto, dato che con meno di due parametri ha poco senso) */
  50.     if (argc < 3) /* Meno di due parametri */  
  51.     {
  52.         printf("Errore nel numero dei parametri\n");
  53.         exit(1);
  54.     }
  55.  
  56.     /* Calcoliamo il numero di file/numeri passati */
  57.     N = argc - 1;
  58.    
  59.     /* Allocazione dell'array di N pipe descriptors figli-padre */
  60.     pipedFP = (pipe_t *) malloc (N*sizeof(pipe_t));
  61.     if (pipedFP == NULL)
  62.     {
  63.         printf("Errore nella allocazione della memoria pipe figli-padre\n");
  64.         exit(2);
  65.     }
  66.    
  67.     /* Allocazione dell'array di N pipe descriptors nipoti-padre */
  68.     pipedNP = (pipe_t *) malloc (N*sizeof(pipe_t));
  69.     if (pipedNP == NULL)
  70.     {
  71.         printf("Errore nella allocazione della memoria pipe nipoti-padre\n");
  72.         exit(3);
  73.     }
  74.    
  75.     /* Creazione delle N pipe figli-padre e delle N pipe nipoti-padre */
  76.     for (i=0; i < N; i++)
  77.     {
  78.         if (pipe(pipedFP[i]) < 0)
  79.         {
  80.             printf("Errore nella creazione della pipe %d-esima figli-padre\n", i);
  81.             exit(4);
  82.         }
  83.         if (pipe(pipedNP[i]) < 0)
  84.         {
  85.             printf("Errore nella creazione della pipe %d-esima nipoti-padre\n", i);
  86.             exit(5);
  87.         }
  88.     }
  89.  
  90.     /* Ciclo di generazione dei figli */
  91.     for (i=0; i < N; i++)
  92.     {
  93.         if ( (pid = fork()) < 0)
  94.         {
  95.             printf("Errore nella fork %d-esima\n", i);
  96.             exit(6);
  97.         }
  98.        
  99.         if (pid == 0)
  100.         {
  101.             /* codice del figlio */
  102.             printf("Sono il processo figlio di indice %d e pid %d sto per creare il nipote che leggera' sempre dal mio stesso file %s\n", i, getpid(), argv[i+1]);
  103.             /* Chiusura delle pipe non usate nella comunicazione con il padre  */
  104.             for (j=0; j < N; j++)
  105.             {
  106.                 close(pipedFP[j][0]);
  107.                 if (i != j) close(pipedFP[j][1]);
  108.             }
  109.  
  110.             if ( (pid = fork()) < 0)
  111.             {
  112.                 printf("Errore nella fork di creazione del nipote\n");
  113.                 exit(-1); /* decidiamo, in caso di errore, di tornare -1 che verra' interpretato come 255 e quindi un valore NON accettabile */
  114.             }  
  115.             if (pid == 0)
  116.             {
  117.                 /* codice del nipote */
  118.                 printf("Sono il processo nipote del figlio di indice %d e pid %d\n", i, getpid());
  119.                 /* chiusura della pipe rimasta aperta di comunicazione fra figlio-padre che il nipote non usa */
  120.                 close(pipedFP[i][1]);
  121.                 /* Chiusura delle pipe non usate nella comunicazione con il padre  */
  122.                 for (j=0; j < N; j++)
  123.                 {
  124.                     close(pipedNP[j][0]);
  125.                     if (i != j) close(pipedNP[j][1]);
  126.                 }
  127.  
  128.                 /* sia il figlio che il nipote devono aprire (con due open separate per avere l'I/O pointer separato) lo stesso file in lettura/scrittura, dato che dovranno operare delle trasformazioni */
  129.                 if ((fd=open(argv[i+1], O_RDWR)) < 0)
  130.                 {
  131.                                     printf("Errore nella open del file %s\n", argv[i+1]);
  132.                     exit(-1); /* decidiamo, in caso di errore, di tornare -1 che verra' interpretato come 255 e quindi un valore NON accettabile */
  133.                             }
  134.                     while (read(fd, &ch, 1))
  135.                 {  
  136.                     /* controlliamo se abbiamo trovato un carattere numerico */
  137.                     if (isdigit(ch))  
  138.                     /* si deve trasformare nel carattere spazio e quindi per prima cosa bisogna tornare indietro di una posizione */
  139.                     {   lseek(fd, -1L, SEEK_CUR);
  140.                         ch = ' '; /* trasformiamo il carattere nello spazio */
  141.                         write(fd, &ch, 1); /* scriviamolo sul file */
  142.                         /* e aggiorniamo il numero di trasformazioni */
  143.                         trasformazioni++;
  144.                     }
  145.                     else
  146.                         ; /* non si deve fare nulla */
  147.                 }
  148.                 /* il nipote deve inviare al padre il numero di trasformazioni operate */
  149.                 write(pipedNP[i][1], &trasformazioni, sizeof(trasformazioni));
  150.                 ritorno=trasformazioni/256;
  151.                 exit(ritorno); /* torniamo il valore richiesto dal testo operando una divisione intera per 256 */
  152.             }
  153.             else
  154.             { /* codice figlio */
  155.                 /* le pipe usate dal nipote vanno chiuse TUTTE */
  156.                 for (j=0; j < N; j++)
  157.                 {
  158.                     close(pipedNP[j][0]);
  159.                     close(pipedNP[j][1]);
  160.                 }
  161.  
  162.                 /* il figlio ha un codice molto simile al nipote, adesso il figlio legge dalla pipe fino a che ci sono caratteri e cioe' linee inviate dal nipote tramite la head */
  163.                 /* sia il figlio che il nipote devono aprire (con due open separate per avere l'I/O pointer separato) lo stesso file in lettura/scrittura, dato che dovranno operare delle trasformazioni */
  164.                 if ((fd=open(argv[i+1], O_RDWR)) < 0)
  165.                 {
  166.                                     printf("Errore nella open del file %s\n", argv[i+1]);
  167.                     exit(-1); /* decidiamo, in caso di errore, di tornare -1 che verra' interpretato come 255 e quindi un valore NON accettabile */
  168.                             }
  169.                     while (read(fd, &ch, 1))
  170.                 {  
  171.                     /* controlliamo se abbiamo trovato un carattere alfabetico MAIUSCOLO */
  172.                                         if (isupper(ch))
  173.                                         /* si deve trasformare nel corrispondente carattere alfabetico minuscolo e quindi per prima cosa bisogna tornare indietro
  174.  di una posizione */
  175.                                         {       lseek(fd, -1L, SEEK_CUR);
  176.                                                 ch = ch + 32; /* trasformiamo il carattere da MAIUSCOLO a minuscolo aggiungendo 32 */
  177.                                                 write(fd, &ch, 1); /* scriviamolo sul file */
  178.                                                 /* e aggiorniamo il numero di trasformazioni */
  179.                                                 trasformazioni++;
  180.                                         }
  181.                                         else
  182.                                                 ; /* non si deve fare nulla */
  183.                                 }
  184.                
  185.                 /* il figlio deve inviare al padre il numero di trasformazioni operate */
  186.                 write(pipedFP[i][1], &trasformazioni, sizeof(trasformazioni));
  187.                 /* il figlio deve aspettare il nipote e stampare il suo pid con il valore ritornato (come richiesto dal testo) */
  188.                 pid = wait(&status);
  189.                 if (pid < 0)
  190.                 {  
  191.                     printf("Errore in wait\n");
  192.                     exit(-1);
  193.                 }
  194.                 if ((status & 0xFF) != 0)
  195.                         printf("Nipote con pid %d terminato in modo anomalo\n", pid);
  196.                     else
  197.                     printf("Il nipote con pid=%d ha ritornato %d\n", pid, ritorno=(int)((status >> 8) & 0xFF));
  198.  
  199.                 /* torniamo il valore richiesto dal testo operando una divisione intera per 256 */
  200.                 ritorno=trasformazioni/256;
  201.                 exit(ritorno);
  202.             }
  203.         }
  204.     }
  205.    
  206. /* Codice del padre */
  207. /* Il padre chiude i lati delle pipe che non usa */
  208.     for (i=0; i < N; i++)
  209.     {
  210.         close(pipedFP[i][1]);
  211.         close(pipedNP[i][1]);
  212.     }
  213.  
  214. /* Il padre recupera le informazioni dai figli in ordine di indice */
  215.  
  216.     for (i=0; i < N; i++)
  217.     {
  218.         read(pipedFP[i][0], &trasformazioni, sizeof(trasformazioni));
  219.         printf("Il figlio di indice %d ha operato %ld trasformazioni di caratteri MAIUSCOLI in minuscoli sul file %s\n", i, trasformazioni, argv[i+1]);
  220.         read(pipedNP[i][0], &trasformazioni, sizeof(trasformazioni));
  221.         printf("Il nipote di indice %d ha operato %ld trasformazioni di caratteri numerici in carattere spazio sullo stesso file %s\n", i, trasformazioni, argv[i+1]);
  222.     }  
  223.     /* Il padre aspetta i figli */
  224.     for (i=0; i < N; i++)
  225.     {
  226.         pid = wait(&status);
  227.         if (pid < 0)
  228.         {
  229.         printf("Errore in wait\n");
  230.         exit(7);
  231.         }
  232.  
  233.         if ((status & 0xFF) != 0)
  234.             printf("Figlio con pid %d terminato in modo anomalo\n", pid);
  235.             else
  236.         { ritorno=(int)((status >> 8) & 0xFF);
  237.           if (ritorno==255)
  238.             printf("Il figlio con pid=%d ha ritornato %d e quindi vuole dire che ci sono stati dei problemi\n", pid, ritorno);
  239.           else  printf("Il figlio con pid=%d ha ritornato %d\n", pid, ritorno);
  240.         }
  241.     }
  242.     exit(0);
  243. }
Add Comment
Please, Sign In to add comment