next up previous contents index
suivant: 7.3 Synchronisation : sémaphores monter: 7. Communications inter-processus précédent: 7.1 Signaux asynchrones   Table des matières   Index

Sous-sections


7.2 Les tubes

Les tubes permettent l'échange bidirectionnel de données entre deux processus s'exécutant sur la même machine.

Figure 7.1: Tube de communication bidirectionnelle entre deux processus A et B.
bp
[width=]ps/tube.ps
bp

Nous avons vu dans la section 3.4.2 comment le shell permet de manipuler très facilement des chaînes de processus reliés par des tubes.


7.2.1 Lancement d'une commande avec popen()

Une première utilisation très pratique des tubes est le lancement d'une commande par un programme C. Nous avons vu plus haut que l'appel system() lançait une commande; cependant il n'est alors pas possible de récupérer directement la sortie de la commande.

La fonction popen() lance un processus exécutant la commande voulue et relie ce processus à l'appelant par un tube unidirectionnel. Les deux processus s'exécutent alors en parallèle.

  FILE *popen( char *command, char *mode );
  int  pclose( FILE *stream );

Le paramètre mode indique le sens du tube ("w" en écriture, "r" en lecture).

La commande est habituellement un filtre. Par exemple, supposons que nous voulions compter le nombre de ligne dans un fichier texte nommé texte.txt" . Une première solution est d'ouvrir le fichier avec fopen(), de le lire en comptant le caractères fin de ligne jusqu'à arriver au bout, puis de le refermer. Une autre solution, plus simple, est d'utiliser la commande existante wc (voir page [*]), comme suit :

  char res[256];                     /* buffer pour resultat */
  FILE *df = popen( "wc -l  texte.txt", "r" );
  fgets( res, 255, df );             /* lecture du resultat  */
  pclose( df );                      /* fermeture du tube    */
  int nblignes = atoi( res );        /* conversion en entier */

7.2.2 Création d'un tube avec pipe()

Il est parfois nécessaire d'échanger de l'information dans les deux sens entre deux processus (modèle client/serveur, etc.).

En langage C, l'appel système pipe() permet la création d'un nouveau tube. Le tube est alors représenté par un couple de descripteurs, l'un pour écrire, l'autre pour lire.

  #include <unistd.h>
  int pipe( int filedes[2]);

En cas d'erreur, la valeur retournée est différente de zéro. pipe() crée une paire de descripteurs et les place dans le tableau filedes[]. filedes[0] est utilisé pour lire dans le tube, et filedes[1] pour y écrire.

Pour l'instant, il n'y a personne à l'autre extrémité du tube. C'est pourquoi l'appel à pipe() est généralement suivi par la création d'un processus fils avec lequel on va communiquer.

Dans ce contexte, l'appel système dup2() est très utile.

  int dup2( int newfd, int oldfd );
dup2() ferme le descripteur oldfd (s'il est ouvert) puis le remplace par le descripteur newfd.

L'appel à dup2() permet par exemple de remplacer l'entrée standard d'un processus par la sortie d'un tube existant.


next up previous contents index
suivant: 7.3 Synchronisation : sémaphores monter: 7. Communications inter-processus précédent: 7.1 Signaux asynchrones   Table des matières   Index
Emmanuel Viennet
1999-01-05