next up previous contents index return to home!
Next: Le IPC di System Up: Comunicazione fra processi Previous: Un Esempio   Indice   Indice analitico

Comunicazione tramite FIFO

Come già accennato, uno dei più grossi problemi che si possono incontrare utilizzando i pipe è che essi possono essere utilizzati solo dal processo che ha creato il pipe o dai suoi discendenti, in quanto i descrittori dei file che costituiscono l'ingresso e l'uscita del pipe sono privati del processo che lo crea e vengono copiati nei processi creati tramite fork().

Per risolvere tale problema, serve un mezzo per permettere ad un processo di identificare un pipe avendone visibilità globale. Una tipica struttura a visibilità globale condivisa da tutti i processi in un sistema Unix è il file system: per questo motivo molte risorse vengono rimappate su file, in modo da renderle accessibili a tutti i processi che ne conoscano il nome. La soluzione più logica è quindi quella di utilizzare il file system per permettere ai processi di accedere ai pipe: tale soluzione è adottata dai pipe con nome, che sono visibili come file. In questo caso i vari processi devono quindi esplicitamente aprire la pipe in ingresso o in uscita (come un normale file) collegando un descrittore all'ingresso o all'uscita del pipe con la syscall open().

I pipe con nome, chiamati anche FIFO, permettono di comunicare a processi ``non imparentati'' fra loro, purché essi si accordino sul nome del FIFO tramite cui comunicare. Per il resto sono del tutto simili ai normali pipe: canali di comunicazione asincroni e monodirezionali accessibili con le normali primitive di I/O di Unix tramite descrittori di file privati del processo. Anche le FIFO hanno un buffer interno di dimensione limitata, come i pipe semplici.

Come per i pipe, una lettura su una FIFO che non è aperta in scrittura ritorna 0 (EOF), mentre una scrittura su una FIFO che non è aperta in lettura genera un segnale SIGPIPE (e la write() ritorna EPIPE).

Una FIFO può essere creata usando la syscall mkfifo(), che ha il seguente prototipo:



#include<sys/types.h>
#include<sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);


Argomenti in ingresso :

pathname
- Nome della FIFO (all'interno del file system)
mode
- Specifica i permessi di accesso alla FIFO.

Valore restituito :

0
- In caso di successo
-1
- In caso di errore.

dove pathname è una stringa che indica il nome della FIFO (vista come file). L'accessibilità alla FIFO è controllata in base allo User ID (che contraddistingue ogni utente nel sistema) come specificato dal parametro mode, che ha lo stesso significato che ha nella syscall open() e può essere ottenuto tramite or aritmetico (l'operatore $\Vert$) di varie costanti:

Una volta che la FIFO è stata creata, i vari processi possono accedervi come ad un normale file, aprendola (creando cioè un descrittore di file che la identifica in lettura o in scrittura) con la syscall open() e quindi effettuando write() o read() sul descrittore ritornato dalla open(). Quando si cerca di aprire una FIFO, il risultato dipende dal tipo di accesso che si richiede (lettura o scrittura), dallo stato della FIFO (numero di processi che l'hanno aperta in lettura o in scrittura) e dai flag specificati nella open().

In particolare, se si apre in sola lettura (O_RDONLY) una FIFO che non è aperta in scrittura e non si specifica il flag O_NONBLOCK, la open() è bloccante fino a che qualche altro processo non apre la FIFO in scrittura. Se invece si specifica il flag O_NONBLOCK nella open(), la syscall ritorna immediatamente. Analogamente, se si tenta di aprire in sola scrittura una FIFO che non è aperta in lettura e non si specifica il flag O_NONBLOCK la open() si blocca fino a che un processo non apre la FIFO in lettura. Se invece si specifica il flag O_NONBLOCK la open() fallisce, con errore ENXIO.


next up previous contents index
Next: Le IPC di System Up: Comunicazione fra processi Previous: Un Esempio   Indice   Indice analitico
Giuseppe Lipari 2002-10-27