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:
head -3
, en fermant le côté sortie du tuyau chez l’enfant 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...);