C dans Unix: fork, waitpid et pipes

Ma question concerne la façon de contrôler l’exécution du processus en ce qui concerne les canaux, et plus particulièrement la mise en œuvre de la fonction wait / waitpid .

Lorsque je crée un tube pour la commande suivante ls | head -3 ls | head -3 , je fais ce qui suit:

  • Je crée le tube, fais le fourrage en créant un enfant
  • Pour l’enfant, j’appelle dup2 pour stdin, j’exécute la commande head -3 , en fermant le côté sortie du tuyau chez l’enfant
  • Pour le parent, j’appelle dup2 pour stdout, j’exécute la commande ls , en fermant le côté entrée de pipe dans le parent

Ma question: sur la base de cette discussion , je dois attendre que l’enfant termine l’exécution, c’est-à-dire l’exécution de head -3 . Mais comment / où puis-je implémenter la fonction waitpid de telle manière qu’elle ne soit pas en conflit avec la commande close[] ?

Basé sur ce grand texte , la description se lit comme suit:

Si le parent veut recevoir des données de l’enfant, il doit fermer fd1 et l’enfant doit fermer fd0. Si le parent veut envoyer des données à l’enfant, il doit fermer fd0 et l’enfant doit fermer fd1. Comme les descripteurs sont partagés entre le parent et l’enfant, nous devons toujours nous assurer de fermer l’extrémité du tuyau qui ne nous concerne pas. Sur une note technique, l’EOF ne sera jamais renvoyé si les extrémités inutiles du tuyau ne sont pas explicitement fermées.

L’enfant devra donc attendre que le parent termine le tuyau avant l’exécution.

J’ai également vu des exemples où deux fourchettes sont fabriquées pour un processus avec un tuyau. Est-ce que cela peut être le but d’éviter des processus de zombies, tout comme la description dans ma copie d’APUE ch.8?

Considérez l’implémentation de code suivante:

  #include  #include  #include  #include  int main() { int pid, status; int fd[2]; char *com1[2]; char *com2[3]; com1[0] = "ls"; com1[1] = NULL; com2[0] = "head"; com2[1] = "-3"; com2[2] = NULL; pipe(fd); if((pid = fork()) == -1) { printf("fork error"); exit(1); } if(pid == 0) { /* Child process closes up output side of pipe */ dup2(fd[0], 0); close(fd[1]); execvp(com2[0], com2); } else { /* if(waitpid(0, WIFEXITED(&status), 0) != pid) { printf("wait error"); } is this even needed here? */ /* Parent process closes up input side of pipe */ dup2(fd[1], 1); close(fd[0]); execvp(com1[0], com1); } exit(0); } 

Je dois admettre que j’ai parcouru de nombreuses questions similaires sur StackExchange. Presque tous sont de contenu spécifique cependant. Ce que je recherche, ce sont des explications de principes et des combinaisons de fonctions. Merci pour votre temps!

Vous ne pouvez pas tous deux vouloir attendre un enfant et exec. Donc, vous devez avoir deux enfants. Il y a deux manières courantes de le faire, soit avoir un processus parent qui crée deux enfants directs et peut / doit alors attendre les deux; ou avoir un enfant qui crée lui-même le second, afin que le parent n’ait à attendre qu’une seule terminaison de processus.

Option 1 (pipe héritée)

 pipe(pi); pid1 = fork(); if (pid1==0) { // child1 // make redirections exec("head"...); } pid2 = fork(); if (pid2==0) { // child2 // make redirections exec("ls"...); } // parent process // close unuseful pipe waitpid(pid1...); waitpid(pid2...); 

Option 2 (le tube n’est visible que par les processus concernés)

 pid1 = fork(); if (pid1==0) { // child pipe(pi); pid2 = fork(); if (pid2==0) { // gran child // make redirections exec("ls"...); } // make redirections exec("head"...); } // parent process waitpid(pid1...);