Pipes Linux en entrée et en sortie

Je voudrais faire ce qui suit dans un programme C sur un système d’exploitation Linux:

  • Créer un PIPE en utilisant un appel système (ou 2)
  • Exécuter un nouveau processus en utilisant exec ()
  • Connectez le STDIN du processus au tuyau créé précédemment.
  • Connectez la sortie du processus à un autre PIPE.

L’idée est de contourner tout access au lecteur à des fins de performance.

Je sais que la création de tuyaux est assez simple en utilisant l’appel système PIPE et que je pourrais simplement utiliser popen pour créer un tuyau à des fins d’entrée ou de sortie.

Mais comment feriez-vous cela pour les entrées et les sorties?

Vous devez faire très attention à la plomberie:

  1. Appelez pipe () deux fois, une pour pipe-to-child, une pour pipe-from-child, donnant 4 descripteurs de fichier.
  2. Appelez fork ().
  3. Chez l’enfant:
    • Appelez close () sur l’entrée standard (descripteur de fichier 0).
    • Appelez dup () – ou dup2 () – pour faire en sorte que la lecture de bout en bout de pipe à enfant soit effectuée en entrée standard.
    • Appelez close () à la fin de la lecture du pipe-to-child.
    • Appelez close () à la fin de l’écriture de pipe-to-child.
    • Appelez close () sur la sortie standard (descripteur de fichier 1).
    • Appelez dup () – ou dup2 () – pour que l’écriture de bout en bout de pipe-from-child dans la sortie standard
    • Appelez close () à l’écriture du bout du tuyau.
    • Appelez close () à la fin de la lecture du tuyau de l’enfant.
    • Exécutez le programme requirejs.
  4. En parent:
    • Appelez fermer à la fin de lecture de pipe-to-child.
    • Appelez la fin à la fin de pipe-from-child.
    • Boucle envoyant des données à l’enfant à la fin de l’écriture du tuyau et à la lecture des données de l’enfant à la lecture du tuyau de l’enfant
    • Lorsqu’il n’y a plus rien à envoyer à un enfant, fermez la fin d’écriture de pipe-to-child.
    • Lorsque toutes les données sont reçues, fermez la fin de lecture du pipe-from-child.

Notez combien il y a de fermetures, surtout chez l’enfant. Si vous utilisez dup2 (), vous n’avez pas à fermer explicitement l’entrée et la sortie standard; Cependant, dup () fonctionne correctement si vous fermez explicitement. Notez également que ni dup () ni dup2 () ne ferme le descripteur de fichier dupliqué. Si vous omettez de fermer les tuyaux, aucun programme ne peut détecter correctement EOF; le fait que le processus en cours puisse toujours écrire sur un canal signifie qu’il n’y a pas de fin EOF sur le canal et que le programme sera suspendu indéfiniment.

Notez que cette solution ne modifie pas l’erreur standard pour l’enfant; il va au même endroit que l’erreur standard pour le parent. C’est souvent correct. Si vous souhaitez que les messages d’erreur de l’enfant soient gérés différemment, prenez les mesures appropriées pour corriger l’erreur standard de l’enfant également.

En fonction de vos besoins, il vous sera peut-être plus simple d’utiliser mkfifo (1) pour créer un canal nommé et pour que vos processus lisent / écrivent dans ce fichier. Bien que le fichier soit nommé dans le système de fichiers, la surcharge liée à l’utilisation d’un canal anonyme ne doit pas être appréciable.

Le moyen le plus simple consiste probablement à exécuter /bin/sh . Vous pouvez ainsi utiliser la syntaxe de shell habituelle pour spécifier les canaux et décharger toutes les complexités.

Quelque chose comme:

 execlp("sh", "-c", "cat /dev/zero | cat > /dev/null", NULL);