Les tubes et les tubes nommés
Les principes
Les tubes permettent à des processus de se transmettre un flux de données sans avoir à le stocker dans un fichier disque. Les tubes peuvent être anonymes (pipes) ou nommés (named pipes). Les premiers ne sont accessibles qu’à des processus apparentés (ayant un processus « ancêtre » commun), les seconds peuvent être utilisés par tout processus ayant les droits d’accès adéquats sur le tube nommé.
Le mécanisme du tube, géré par le noyau, vient du système Unix et se retrouve sur tous les systèmes de type Unix (et aussi sur Windows). Il est surtout utilisé pour échanger des données entre processus, mais peut également servir d’outil de synchronisation entre processus.
1. Flot d’octets (bytestream)
Un tube (anonyme ou nommé) est géré par le noyau comme un flot d’octets (bytestream) unidirectionnel, établi entre plusieurs processus. Il est unidirectionnel au sens où un processus peut écrire ou lire dans le tube, mais pas les deux. On distingue des processus écrivains et des processus lecteurs.
Une fois le tube créé et ouvert par au moins un processus écrivain et au moins un processus lecteur, les processus écrivent ou lisent des données dans le tube, via les appels système standards d’écriture et de lecture fichiers, write() et read(). Ils peuvent également utiliser l’appel système fcntl() pour modifier les attributs...
Les tubes anonymes (pipes)
Un tube anonyme est associé à un inode n’existant qu’en mémoire et n’a pas de nom (de lien) pointant sur cet inode. Il ne peut donc pas être créé ni ouvert par l’appel système open(). D’autre part, seul un processus apparenté au processus créateur du tube pourra y accéder.
Dans la suite du chapitre, nous utiliserons le terme tube pour désigner un tube anonyme.
1. Création d’un tube
L’appel système pipe() permet de créer un tube.
Syntaxe
#include <unistd.h>
int pipe(int fildes[2]);
Arguments
fildes |
Tableau de deux entiers pour les descripteurs de fichier ouvert retournés par l’appel |
Valeur retournée
-1 |
Erreur, code erreur positionné dans la variable errno |
0 |
Succès |
Description
Cet appel système crée un tube et fournit deux descripteurs de fichier ouvert, le premier (fildes[0]) ouvert en lecture, le second (fildes[1]) ouvert en écriture. Le noyau affecte au tube les deux plus petits descripteurs de fichier disponibles. Pour un processus n’ayant que les entrées/sorties standards ouvertes, ce seront les descripteurs 3 et 4.
Ces descripteurs peuvent être utilisés avec les appels système de gestion de fichier, read(), write(), fcntl(), etc. Cependant, les caractéristiques par défaut de ces appels, dans le cas d’accès à un tube, sont spécifiques en raison de la nature particulière des tubes : gestion uniquement en mémoire, mode FIFO avec suppression des données lues, lecture/écriture bloquante.
Il n’y a pas de contrôle d’accès en fonction du compte utilisateur et du groupe pour un tube. En effet, ce contrôle se fait à l’ouverture d’un fichier, or un tube ne peut être accédé que par des processus ayant déjà un descripteur de fichier ouvert sur lui. Le seul contrôle est donc sur le type d’accès, lecture ou écriture en fonction du descripteur utilisé.
Le tube est maintenu par le noyau tant qu’au moins un processus a un descripteur de fichier ouvert associé au tube.
Comme tout descripteur de fichier ouvert, les descripteurs de fichier ouvert associés au tube sont hérités...
Les tubes nommés
Un tube nommé, aussi appelé fichier FIFO (First In First Out) est un tube qui est associé à un nom dans l’arborescence d’un système de fichier. Cela implique qu’il ait un inode dans le système de fichiers, sur lequel pointe au moins un lien dans un répertoire. L’inode contient les attributs classiques d’un fichier (type, droits d’accès, propriétaire, groupe, nombre de liens, taille, dates), avec quelques particularités :
-
Le type de fichier est S_IFIFO : il s’agit d’un fichier en mode FIFO, avec lecture destructive, dans l’ordre des écritures : Premier écrit Premier Lu (First In First Out).
-
Sa taille hors utilisation est toujours nulle : les données dans le fichier sont transitoires et gérées dans un buffer en mémoire vive, par le noyau. Quand tous les processus ont fermé le tube nommé, le buffer est libéré par le noyau, son contenu éventuel est perdu.
-
Il n’y a aucun bloc de données associé au fichier. Un tube nommé n’occupe donc pas d’espace disque, hormis celui nécessaire à son entrée dans la table des inodes et aux entrées de ses liens physiques dans les tables des répertoires.
Un tube nommé s’ouvre comme un fichier, avec l’appel système open(), en fournissant son chemin d’accès. Par conséquent, contrairement aux tubes anonymes, il est utilisable par n’importe quel processus, sous réserve du contrôle d’accès.
Une fois ouvert, un tube nommé se manipule avec les appels système classiques, read(), write(), close(). Comme les tubes anonymes, il n’accepte pas les appels de déplacement de la position courante (appels de type lseek()).
1. Création d’un tube nommé
Un tube nommé se crée par un appel système spécifique, mkfifo(). On ne peut donc pas utiliser l’appel système open() avec l’option O_CREAT. Pour ouvrir un tube nommé, il faut qu’il existe.
La commande mkfifo permet de créer un tube nommé :
mkfifo [-m Permissions] NomTube
Syntaxe
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
Arguments
path |
Chemin d’accès... |