Maison  >  Article  >  développement back-end  >  Comment puis-je diriger correctement les entrées et sorties standard vers un processus enfant sous Linux ?

Comment puis-je diriger correctement les entrées et sorties standard vers un processus enfant sous Linux ?

Linda Hamilton
Linda Hamiltonoriginal
2024-11-08 19:39:02225parcourir

How can I properly pipe standard input and output to a child process in Linux?

Exécution de processus enfants avec entrée et sortie standard canalisées sous Linux

Considérez la fonction suivante :

string f(string s) {
    string r = system("foo < s");
    return r;
}

Ceci La fonction tente d'exécuter le programme "foo" avec la chaîne s comme entrée standard, capturant la sortie standard du programme dans la chaîne r. Cependant, cette approche n'est pas viable.

Pour implémenter correctement cette fonctionnalité, une combinaison d'appels système Linux ou de fonctions POSIX est requise :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int createChild(const char *szCommand, char *const aArguments[], char *const aEnvironment[],
               const char *szMessage) {
  int aStdinPipe[2];
  int aStdoutPipe[2];
  int nChild;
  char nChar;

  if (pipe(aStdinPipe) < 0) {
    perror("allocating pipe for child input redirect");
    return -1;
  }
  if (pipe(aStdoutPipe) < 0) {
    close(aStdinPipe[PIPE_READ]);
    close(aStdinPipe[PIPE_WRITE]);
    perror("allocating pipe for child output redirect");
    return -1;
  }

  nChild = fork();
  if (0 == nChild) {
    // child continues here

    // redirect stdin
    if (dup2(aStdinPipe[PIPE_READ], STDIN_FILENO) == -1) {
      exit(errno);
    }

    // redirect stdout
    if (dup2(aStdoutPipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
      exit(errno);
    }

    // redirect stderr
    if (dup2(aStdoutPipe[PIPE_WRITE], STDERR_FILENO) == -1) {
      exit(errno);
    }

    // run child process image
    // (replace this with any `exec*` function you find easier to use)
    execve(szCommand, aArguments, aEnvironment);

    // if we get here at all, an error occurred, but we are in the child
    // process, so just exit
    exit(errno);
  } else if (nChild > 0) {
    // parent continues here

    // close unused file descriptors
    close(aStdinPipe[PIPE_READ]);
    close(aStdoutPipe[PIPE_WRITE]);

    // send message to child (if provided)
    if (NULL != szMessage) {
      write(aStdinPipe[PIPE_WRITE], szMessage, strlen(szMessage));
    }

    // read child's output
    while (read(aStdoutPipe[PIPE_READ], &nChar, 1) == 1) {
      write(STDOUT_FILENO, &nChar, 1);
    }

    // close pipes
    close(aStdinPipe[PIPE_WRITE]);
    close(aStdoutPipe[PIPE_READ]);
  } else {
    // failed to create child
    close(aStdinPipe[PIPE_READ]);
    close(aStdinPipe[PIPE_WRITE]);
    close(aStdoutPipe[PIPE_READ]);
    close(aStdoutPipe[PIPE_WRITE]);
  }
  return nChild;
}

Cette fonction createChild met en place un canal entre le processus parent et enfant, redirigeant l'entrée et la sortie standard de l'enfant vers et depuis le tube. Le processus parent peut ensuite envoyer une entrée à l'enfant via le canal et lire la sortie de l'enfant à partir du même canal.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn