Corso di Laurea in Ing. Informatica, Universita' La Sapienza
Sistemi Operativi II
Docente Roberto Baldoni

Esempio di domanda di programmazione (argomento: PIPE - Appello del 19 Luglio 2004).

Si vuole realizzare un programma in cui viene creata una lista di processi (un progenitore istanzia un processo figlio, che a sua volta ne istanzia un'altro e così via). La lunghezza della lista di processi è arbitraria e scelta a tempo di esecuzione. Ogni processo una volta istanziato genera un numero random. L'ultimo processo istanziato (il numero 6 della figura) comunica il numero generato al padre; tutti i processi intermedi leggono dal loro processo figlio un numero (il processo 5 ad esempio legge 4 dal processo 6), lo sommano al proprio e mandano la somma al loro processo padre. Una volta ottenuta la somma totale, il processo progenitore (nell'esempio il processo 1) la stampa a video.

Di seguito viene riportato lo scheletro del codice, da completare a cura dello studente, che realizza l'applicazione descritta Notare che la comunicazione tra i vari processi avviene tramite PIPE.

 

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>

int
my_random();

int
main(int argc, char * argv[]) {
   int lunghezza, figlio, i, status, num, num2;
   int nextPIPE[2], pipeSUP;

   if (argc==1) {
      printf("Sintassi: %s numero nodi\n",argv[0]);
      exit(1);
   }

   lunghezza = atoi(argv[1]);
   if (lunghezza == 1) {
      printf("Immettere un valore maggiore o uguale a 2\n");
      exit(1);
   }

   // init della pipe che collega un nodo con il padre
   // solo per il nodo iniziale pipeSUP sarà
   // uguale a -1
   pipeSUP = -1;

   i = 1;
   while (i < lunghezza) { // si devono generare figli

      // creo la pipe che collega un nodo col figlio
      if (pipe(nextPIPE) < 0) {
         printf("Processo %d: errore nella creazione della pipe per la comunicazione col figlio\n", getpid());
         exit(1);
      }
      figlio = fork();
      if (figlio != 0) { // processo padre
         //
         // codice mancante
         //
      }
      else { // processo figlio
         pipeSUP = nextPIPE[1];
         close(nextPIPE[0]);
         i++;
         if (i == lunghezza) { // non si devono più creare processi
            printf("Processo %d: nodo figlio; ",getpid());

            num = my_random();
            printf("valore generato = %d\n",num);
            if (write(pipeSUP, &num, sizeof(int))==-1) {
               printf("Processo %d: errore durante la send\n", getpid());
               exit(1);
            }
            else
               printf("Processo %d: send di %d al processo %d riuscita\n", getpid(), num, getppid());

            close(pipeSUP);
            break;
         }
      }
   }
}

int
my_random() { // genera un numero casuale tra 1 e 10
   struct timeval t;

   gettimeofday(&t, NULL);

   srand(t.tv_sec/1000+t.tv_usec*1000);
   return (1+(int) (10.0*rand()/(RAND_MAX+1.0)));
}