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

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

Le operazioni che ogni nodo intermedio della catena deve effettuare sono le seguenti:

  1. leggere dalla pipe che lo collega al figlio un intero;
  2. sommare il numero letto a quello da lui generato;
  3. scrivere nella pipe che lo collega al padre la somma risultante; quest'ultimo passo non sarà ovviamente eseguito dal processo progenitore (quello che nella figura è etichettato come processo 0) che invece stamperà la somma a video.

C'è da notare che il descrittore di file pipeSUP ha un significato ben preciso: è il riferimento al canale di scrittura della pipe che collega un processo con il relativo padre. Quindi NON SI DEVE MODIFICARE il suo valore, mentre nextPIPE rappresenta il collegamento con il processo figlio. Durante la fase di creazione della catena, tutti i nodi intermedi passano da una fase in cui sono "figli" (ramo else dell'if fork) ad una in cui diventano "padri" (successiva fork dovuta al ciclo while): ed è in questa fase che il riferimento al canale di scrittura col processo padre viene "salvato" (assegnando a pipeSUP in valore di nextPIPE[1], che in quel punto specifico del codice rappresenta proprio il collegamento col padre). Al successivo ciclo, nextPIPE assumerà nuovi valori relativi alla nuova pipe, e quindi l'unico riferimento alla vecchia pipe rimane pipeSUP

Di seguito viene riportato il codice della soluzione proposta. E' possibile prelevare il file completo qui.

 
         close(nextPIPE[1]);

         printf("Processo %d: nodo", getpid());
         if (pipeSUP == -1) printf(" iniziale ");
         else printf(" intermedio ");
         printf(": -> figlio = %d\n", figlio);

         // read su pipeSX[0]
         if (read(nextPIPE[0], &num, sizeof(int)) == -1) {
            printf("Processo %d: errore durante la receive\n",getpid());
            exit(1);
         }
         else
            printf("Processo %d: ricevuto %d dal figlio.\n", getpid(), num);

         num2 = my_random();
         printf("Processo %d: nodo", getpid());
         if (pipeSUP == -1) printf(" iniziale ");
         else printf(" intermedio ");
         printf(": valore generato = %d\n", num2);

         num += num2;
         if (pipeSUP != -1) // write su pipeSUP se != -1
            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);
            }
         else // else sto alla radice e quindi stampo.
            printf("Processo %d: il Risultato della somma è: %d\n", getpid(), num);

         wait(&status);
         break;