Comment fonctionne Un pipe sous Linux?
Comment fonctionne la tuyauterie? Si j'exécute un programme via CLI et redirige la sortie vers un fichier, est-ce que je serai capable de pipe ce fichier dans un autre programme tel qu'il est écrit?
fondamentalement, quand une ligne est écrite dans le fichier, je voudrais qu'elle soit acheminée immédiatement à ma deuxième application (j'essaie de dessiner dynamiquement un graphique à partir d'un programme existant). Juste savoir si la tuyauterie complète la première commande avant de passer à la commande suivante.
Tout feedback serait grandement apprécié!
4 réponses
si vous voulez rediriger la sortie d'un programme dans l'entrée d'un autre, utilisez simplement un pipeline simple:
program1 arg arg | program2 arg arg
si vous voulez enregistrer la sortie de program1
dans un fichier et Piper il dans program2
, vous pouvez utiliser tee(1)
:
program1 arg arg | tee output-file | program2 arg arg
tous les programmes d'un pipeline sont exécutés simultanément. La plupart des programmes utilisent généralement blocage I / O: Si quand ils essaient de lire leurs entrées et que rien n'est là, ils bloquent : c'est-à-dire qu'ils s'arrêtent, et le système d'exploitation les dés-programment pour courir jusqu'à ce que plus d'entrées deviennent disponibles (pour éviter de manger le CPU). De même, si un programme plus tôt dans le pipeline écrit des données plus rapidement qu'un programme plus tard ne peut les lire, le tampon du pipe finit par se remplir et l'auteur bloque: L'OS le dés-programme jusqu'à ce que le tampon du pipe soit vidé par le lecteur, et alors il peut continuer à écrire de nouveau.
modifier
si vous voulez utiliser la sortie de program1
comme paramètres de ligne de commande, vous pouvez utiliser les backquotes ou la syntaxe $()
:
# Runs "program1 arg", and uses the output as the command-line arguments for
# program2
program2 `program1 arg`
# Same as above
program2 $(program1 arg)
la syntaxe $()
devrait être préférée, car elles sont plus claires et peuvent être imbriquées.
Tuyauterie ne complète pas la première commande avant de lancer le deuxième . La tuyauterie Unix (et Linux) exécute toutes les commandes simultanément. Une commande sera suspendue si
-
il est affamé pour l'entrée.
-
il a produit beaucoup plus de production que son successeur est prêt à consommer.
pour la plupart des programmes sortie est tamponné , ce qui signifie que L'OS accumule une quantité substantielle de sortie (peut-être 8000 caractères ou plus) avant de la transmettre à l'étape suivante du pipeline. Ce tampon est utilisé pour éviter de trop basculer entre les processus et le noyau.
si vous voulez que la sortie sur un pipeline soit envoyée tout de suite, vous pouvez utiliser unbuffered I/ O, qui en C signifie appeler quelque chose comme fflush()
pour être sûr que toute sortie tamponnée est immédiatement envoyée sur le processus suivant. L'Entrée libre est également possible mais généralement inutile car un processus qui est privé d'entrée n'attend généralement pas un tampon complet mais traitera toutes les entrées que vous pouvez obtenir.
pour les applications typiques, la sortie non tamponnée n'est pas recommandée; vous obtenez généralement les meilleures performances avec les valeurs par défaut. Dans votre cas, cependant, où vous voulez faire le graphique dynamique immédiatement le premier processus a l'info disponible, vous voulez certainement être en utilisant la sortie non tamponnée. Si vous utilisez C, appeler fflush(stdout)
à chaque fois que vous voulez que la sortie soit envoyée sera suffisant.
si vos programmes communiquent en utilisant stdin
et stdout
, assurez-vous que vous appelez fflush(stdout)
après avoir écrit ou trouvez un moyen de désactiver le tampon IO standard. La meilleure référence que je puisse penser qui puisse vraiment décrire la meilleure façon d'implémenter des pipelines en C/C++ est Advanced Programming in the UNIX Environment ou UNIX Network Programming: Volume 2 . Vous pourriez probablement commencer par un cet article ainsi.
si vos deux programmes insistent sur la lecture et l'écriture de fichiers et n'utilisent pas stdin/stdout, vous pouvez trouver que vous pouvez utiliser un appelé pipe au lieu d'un fichier.
créer un tube nommé avec la commande mknod(1):
$ mknod /tmp/named-pipe p
configurez ensuite vos programmes pour lire et écrire dans /tmp/named-pipe (utilisez le chemin/nom que vous jugez approprié).
dans ce cas, les deux programmes seront exécutés en parallèle, bloquer au besoin lorsque le tuyau devient plein/vide comme décrit dans les autres réponses.