pipe(2)
Appel système
Crée un tube à sens unique dans le noyau et renvoie deux descripteurs, un pour lire et un pour écrire. Combiné à fork, il relie deux processus.
#include <unistd.h>
int pipe(int pipefd[2]);Description
pipe crée un canal de communication à sens unique et remplit le tableau qu'on lui passe avec deux descripteurs de fichiers : pipefd[0] est l'extrémité de lecture, pipefd[1] l'extrémité d'écriture. Ce qu'on écrit dans pipefd[1] avec write se lit dans le même ordre dans pipefd[0] avec read. Entre les deux, les données attendent dans un tampon du noyau (16 pages sous Linux, soit 65 536 octets avec des pages de 4 Kio).
Seul, un pipe ne sert pas à grand-chose. Créé avant un fork, il est hérité par l'enfant, et les deux processus tiennent alors chacun les deux extrémités du même tuyau. L'un écrit, l'autre lit, et chacun ferme l'extrémité qu'il n'utilise pas. C'est le mécanisme du | du shell, avec dup2 pour brancher le tuyau sur l'entrée ou la sortie standard.
Valeur de retour
0 en cas de succès. -1 en cas d'erreur, avec errno (EMFILE quand le processus a atteint sa limite de descripteurs ouverts, ENFILE pour la limite du système) ; le tableau n'est alors pas modifié.
Pièges
readne renvoie 0, la fin du flux, que quand toutes les extrémités d'écriture sont fermées, dans tous les processus. Unpipefd[1]oublié ouvert dans le parent suffit à bloquer le lecteur pour toujours.Écrire dans un pipe dont plus personne ne tient l'extrémité de lecture envoie le signal
SIGPIPE, qui termine le processus par défaut.Un pipe plein bloque
writejusqu'à ce que le lecteur consomme des données. Deux processus qui s'écrivent l'un à l'autre sans lire peuvent se bloquer mutuellement.Les deux extrémités restent des descripteurs ordinaires : pense à les fermer comme n'importe quel fichier.
Exemple
#include <stdio.h>#include <sys/wait.h>#include <unistd.h>
int main(void){ int fd[2]; char buf[64]; ssize_t n;
if (pipe(fd) == -1) { perror("pipe"); return 1; } if (fork() == 0) { close(fd[1]); while ((n = read(fd[0], buf, sizeof buf)) > 0) write(STDOUT_FILENO, buf, n); close(fd[0]); return 0; } close(fd[0]); write(fd[1], "message du parent\n", 18); close(fd[1]); wait(NULL); return 0;}$ gcc -Wall -Wextra tube.c -o tube$ ./tubemessage du parentL'enfant ferme l'écriture et lit jusqu'à la fin du flux ; le parent ferme la lecture, écrit, puis ferme l'écriture. Ce dernier close est ce qui permet à la boucle de l'enfant de se terminer.
pipe_chain
Écris pipe_chain, qui place un pipe entre chaque paire de commandes d'une liste et ferme chaque extrémité dont un processus n'a plus besoin.