==============================================================================
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
--------------------[ previous ]---[ index ]---[ next ]---------------------

----------------[ PR0GRAMMAZi0NE UNiX: GESTi0NE DEi PR0CESSi ]----------------
-------------------[ PARTE III : NAMED PiPE & UNAMED PiPE ]-------------------
----------------------------------[ pIGpEN ]----------------------------------

Una named pipe non e' altro che un file creato di default con permesso 0666,
il cui scopo e' quello di permettere il trasferimento di dati tra processi
tra loro non collegati da un rapporto padre/figlio tipico del forking.
In genere e' piu' facile sentir parlare di questa bestiolina con il nome fifo
(First In First Out). Come tutte le pipe, il suo scopo sara' quello di
trasferire l'output di uno o piu' processi nell'input di un altro.

NB: Le named pipe sono tipiche di unix e hanno trovato pure implementazione
ad esempio nel SMB per permette lo scambio di chiamate API e in winzozz.
Un esempio del loro uso su unix lo potete vedere per esempio in syslog.conf
se per esempio avete il diald o dei log particolari...

Dal punto di vista della programmazione, quando eravamo in presenza di una
fork() era possibile che i due processi dialogassero tra di loro attraverso
una unamed pipe.
Questa poteva essere ottenuta in vari modi:

- creare un array di interi [con 2 elementi] e usare la funzione pipe()
  A questo punto il primo elemento viene utilizzato per la lettura ed il
  secondo per la scrittura (fatta attraverso le funzioni read() e write() )

// Andatevi a vedere l'introduzone all' IPC 4.4 BSD (facile da trovare)

#include <stdio.h>

#define DATA "Bright star, would I were steadfast as thou art . . ."

/*
 * This program creates a pipe, then forks.  The child communicates to the
 * parent over the pipe. Notice that a pipe is a one-way communications
 * device.  I can write to the output socket (sockets[1], the second socket
 * of the array returned by pipe()) and read from the input socket
 * (sockets[0]), but not vice versa.
 */

main()
{
     int sockets[2], child;

     /* Create a pipe */
     if (pipe(sockets) < 0) {
          perror("opening stream socket pair");
          exit(10);
     }

     if ((child = fork()) == -1)
          perror("fork");
     else if (child) {
          char buf[1024];

          /* This is still the parent.  It reads the child's message. */
          close(sockets[1]);
          if (read(sockets[0], buf, 1024) < 0)
               perror("reading message");
          printf("-->%s\n", buf);
          close(sockets[0]);
     } else {
          /* This is the child.  It writes a message to its parent. */
          close(sockets[0]);
          if (write(sockets[1], DATA, sizeof(DATA)) < 0)
               perror("writing message");
          close(sockets[1]);
     }
}

- fare la stessa cosa solo utilizzando la generica funzione socketpair()
  per connettere i due processi

- usare la funzione popen() che restituisce una stream e la pclose() per
  chiudere la pipe

Anche con le named pipe esistono due funzioni (che fanno praticamente la stessa
cosa, ma non sempre le trovate entrambe implementate).. sisi' ne esisterebbe
una terza, ma non vado a complicare la vita.

- l'immancabile mknod()

/* set the umask explicitly, you don't know where it's been */
umask(0);

if (mknod("test_fifo",
            S_IFIFO | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
           0))
{
    perror("mknod");
    exit(1);
}

- oppure la mkfifo()

/* set the umask explicitly, you don't know where it's been */
umask(0);
if (mkfifo("test_fifo", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP))
{
    perror("mkfifo");
    exit(1);
}

L'apertura della named pipe avverra' attraverso la open() che sara' bloccata
fino a quando un processo aprira' la pipe in scrittura (salvo che oltre
all'O_RDONLY sia specificata anche la flag O_NONBLOCK).
Cio' vale anche quando aprite la pipe in scrittura e non specificate
l'O_NONBLOCK.
Dopo l'apertura basta utilizzare la read() o la write() a seconda di cosa
dovete fare.

- la read() restituira' EOF quando tutti i processi che scrivevano sulla pipe
  l'avranno lasciata.

- la write() restituira' SIGPIPE quando tutti i processi che leggevano sulla
  pipe avranno chiuso la pipe.

ok, bauz
pIGpEN


--------------------[ previous ]---[ index ]---[ next ]---------------------
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
==============================================================================