Page préc.
Les moniteurs
Fin de page Page suiv.
Les IPCs de Win32

Les pipes

    Les techniques que nous avons étudiées jusqu'ici sont essentiellement destinées à la synchronisation des processus, les quantités d'information transmises étant nulles ou très faibles (la valeur du compteur d'un sémaphore par exemple). Une exception cependant : les moniteurs, qui peuvent avoir des variables locales importantes.

    Les pipes et la mémoire partagée sont les moyens universels de communiquer entre processus sur la même machine, auxquels il faut ajouter des techniques spécifiques à chaque système d'exploitation.

Définition d'un pipe

    Un pipe est une file gérée par le système d'exploitation, implémentée en mémoire partagée, dans laquelle les processus peuvent lire et écrire, selon l'ordre FIFO, un peu comme dans un buffer circulaire. Il peut aussi être décrit comme un tuyau à deux extrémités. Un pipe supporte les opérations d'E/S classiques (read, write). Selon la norme Posix, les pipes sont half-duplex, ce qui signifie que ce ne sont pas les mêmes processus qui lisent ou qui écrivent dans un pipe donné. Il est donc plus fréquent que deux processus communiquent par deux pipes, chacun ayant un sens unique. Certains systèmes comme Unix System V, les implémentent en full-duplex : deux processus peuvent échanger des informations sur le même pipe. Le processus qui crée un pipe est considéré comme serveur du pipe. Le processus qui se connecte sur un pipe existant est un client du pipe. La taille du pipe (en octets) est soit imposée (Unix), soit fixée par l'utilisateur (Win32).

    Sauf dispositions particulières explicites, les opérations d'E/S sur les pipes sont bloquantes par défaut : une lecture dans un pipe est bloquante si le pipe est vide, une écriture est bloquante si le pipe est plein.

    Les pipes sont souvent utilisés pour rediriger les E/S standard des processus (clavier/écran). Par leur nature, les opérations sur les pipes sont en général classées dans les opérations sur les fichiers.

    Il existe généralement deux types de pipes : les pipes anonymes et les pipes nommés.

Pipe anonyme ou pipe non nommé

    Un pipe anonyme est un pipe créé par un processus et qui n'apparaît pas dans les ressources générales du système d'exploitation. Il est seulement connu du processus qui l'a créé et éventuellement de ses processus fils, par l'intermédiaire d'un entier appelé descripteur de fichier (file descriptor) en Unix ou poignée (handle [1]) en Win32. Dans les deux S.E. la création d'un pipe renvoie en fait deux file descriptors ou handles, désignant le pipe comme support des opérations de lecture pour le premier et d'écriture pour le second. L'utilisation des pipes anonymes est donc réservé à des processus affiliés. Un pipe anonyme disparaît lorsque tous les descripteurs de fichiers ou handle ont été fermés ou lorsque plus aucun des processus qui l'utilisaient n'existe.

Pipes nommés

    Contrairement aux pipes anonymes, les pipes nommés sont utilisables pour faire communiquer des processus non affiliés : le processus serveur de pipe crée le pipe en lui donnant un nom, géré par le S.E., qui est accessible par tout processus, comme un nom de fichier. Le comportement et les opérations sur un pipe nommé sont en tout point identiques à ceux d'un pipe anonyme. La seule différence est que le pipe nommé continue d'exister tant qu'il n'est pas explicitement détruit par un processus.

Pipes de Win32

    Les pipes de Win32 sont en tout point conformes à la définition générale donnée ci-dessus.

Fonctions de bas niveau _pipe()

#include <io.h>
#include <fcntl.h> // pour les constantes _O_BINARY et _O_TEXT
#include <errno.h>

int _pipe (int phandles [2],   // handles de lecture et d'écriture
           unsigned int psize, // Nombre d'octets à réserver en mémoire
           int textmode        // mode du pipe
);

    Le paramètre textmode indique le mode de traduction du pipe. Il peut prendre deux valeurs :

    L'utilisation en mode multitâches (multithreaded programs) nécessite quelques précautions d'emploi (voir manuel d'utilisation de la fonction).

    Les opérations d'E/S doivent être réalisées au moyen des fonctions _read() et _write(). Les fonctions _dup() et _dup2() peuvent aussi être utilisées pour effectuer les redirections.

Fonctions CreatePipe() et CreateNamedPipe() de Visual C++

    Les fonctions CreatePipe() et CreateNamedPipe() permettent de créer un pipe anonyme ou nommé:
 
BOOL CreatePipe (
   PHANDLE hReadPipe,                      // address of variable for read handle
   PHANDLE hWritePipe,                     // address of variable for write handle
   LPSECURITY_ATTRIBUTES lpPipeAttributes, // pointer to security attributes
   DWORD nSize                             // number of bytes reserved for pipe
);

HANDLE CreateNamedPipe (
   LPCTSTR lpName,                            // pointer to pipe name
   DWORD dwOpenMode,                          // pipe open mode
   DWORD dwPipeMode,                          // pipe-specific modes
   DWORD nMaxInstances,                       // maximum number of instances
   DWORD nOutBufferSize,                      // output buffer size, in bytes
   DWORD nInBufferSize,                       // input buffer size, in bytes
   DWORD nDefaultTimeOut,                     // time-out time, in milliseconds
   LPSECURITY_ATTRIBUTES lpSecurityAttributes // pointer to security attributes
                                              // structure
);

    Les identificateurs des paramètres sont suffisamment explicites. Les opérations d'E/S doivent être réalisées au moyen des fonctions ReadFile() et WriteFile().

Pipes d'Unix

    Les pipes d'Unix sont en tout point conformes à la définition générale donnée ci-dessus. Un complément et des précisions sont données dans le complément de cours consacré aux supports de Linux au modèle Producteurs/Consommateurs.

    Ils sont créés par la fonction pipe() pour les pipes anonymes, et mkfifo() pour les pipes nommés. La plupart des fonctions applicables aux fichiers le sont aussi aux pipes : read(), write(), close() etc. à l'exception de lseek(). Par défaut les opérations d'E/S sont bloquantes.



[1] Nous utiliserons désormais le terme anglais handle, d'un usage beaucoup plus répandu.


Page préc.
Les moniteurs
Début de page Page suiv.
Les IPCs de Win32
Dernière mise à jour : 10/10/2001