| 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.
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 */
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.