Page suivante Page précédente Table des matières

8. Pipes et FIFOs

Les pipes et les FIFOs permettent de faire communiquer des processus d'une même machine : ce qu'un (ou plusieurs) processus écrit peut être lu par un autre.

8.1 FIFOs

Les FIFOs sont également appelés « tuyaux nommés ». Ce sont des objets visibles dans l'arborescence des fichiers et répertoires. Ce qu'un processus écrit dans une FIFO peut être lu immédiatement par d'autres processus.

#include <stdio.h>
int mkfifo (const char *path, mode_t mode);

La fonction mkfifo() crée un FIFO ayant le chemin indiqué par path et les droits d'accès donnés par mode. Si la création réussit, la fonction renvoie 0, sinon -1. Exemple:

        if(mkfifo("/tmp/fifo.courrier",0644) == -1)
           perror("mkfifo");

Les FIFOS sont ensuite utilisables par open(), read(), write(), close(), fdopen() etc.

Exercice. Regarder ce qui se passe quand

Exercice. Ecrire une commande mutex qui permettra de délimiter une section critique dans des shell-scripts. Exemple d'utilisation :

mutex -b /tmp/foobar
...
mutex -e /tmp/foobar
Le premier paramètre indique si il s'agit de verrouiller (-b = begin) ou de déverrouiller (-e = end). Le second paramètre est le nom du verrou.

Conseil : la première option peut s'obtenir en tentant de lire un jeton dans une FIFO. C'est la seconde option qui dépose le jeton. Prévoir une option pour créer une FIFO ?

8.2 Pipes

On utilise un pipe (tuyau) pour faire communiquer un processus et un de ses descendants

ou des descendants - au sens large - du processus qui ont crée le tuyau
.

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

L'appel pipe() fabrique un tuyau de communication et renvoie dans un tableau une paire de descripteurs. On lit à un bout du tuyau (sur le descripteur de sortie fildes[0]) ce qu'on a écrit dans l'autre (filedes[1]).

Voir exemple dans fork.

Les pipes ne sont pas visibles dans l'arborescence des fichiers et répertoires, par contre ils sont hérités lors de la création d'un processus.

La fonction socketpair() (voir socketpair) généralise la fonction pipe.

8.3 Pipes depuis/vers une commande

#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);

popen() lance la commande décrite par la chaîne command et retourne un flot.

Si type est "r" le flot retourné est celui de la sortie standard de la commande (on peut y lire). Si type est "w" c'est son entrée standard.

pclose() referme ce flot.

Exemple : envoi d'un « ls -l » par courrier


 
  1     /* avis.c */

  2     /* Illustration de popen() */

  3     #include <sys/types.h>
  4     #include <fcntl.h>
  5     #include <stdlib.h>
  6     #include <unistd.h>
  7     #include <stdio.h>

  8     #define TAILLE_MAX_COMMANDE 100

  9     int main(int argc, char *argv[])
 10     {
 11             char cmdmail[TAILLE_MAX_COMMANDE];
 12             FILE *fls, *fmail;
 13             int c;

 14             if (argc != 2) {
 15                     fprintf(stderr, "Usage: %s destinataire\n", argv[0]);
 16                     exit(EXIT_FAILURE);
 17             };

 18             snprintf(cmdmail, TAILLE_MAX_COMMANDE, "sendmail %s",
 19                      argv[1]);
 20             fmail = popen(cmdmail, "w");
 21             if (fmail == NULL) {
 22                     perror("popen(sendmail)");
 23                     exit(EXIT_FAILURE);
 24             };

 25             fprintf(fmail, "Subject: ls -l\n\n");
 26             fprintf(fmail, "Cher %s,\nvoici mon répertoire:\n", argv[1]);

 27             fls = popen("ls -l", "r");
 28             if (fls == NULL) {
 29                     perror("popen(ls)");
 30                     exit(EXIT_FAILURE);
 31             };

 32             while ((c = fgetc(fls)) != EOF)
 33                     fputc(c, fmail);

 34             pclose(fls);

 35             fprintf(fmail, "---\nLe Robot\n");
 36             pclose(fmail);
 37             exit(EXIT_SUCCESS);
 38     }
 


Page suivante Page précédente Table des matières