Comment chaîner stdout dans un processus enfant pour stdin dans un autre enfant en C?

Je déconne en C d’essayer de comprendre comment faire cela. Disons que j’ai mon programme principal, le processus parent. Le parent crée trois processus enfants, dont chacun finira par exécuter des programmes (mais ce n’est pas important pour le moment). Ce que j’aimerais faire, c’est faire en sorte que le stdin du premier enfant soit reçu par le stdin du deuxième enfant. La sortie standard du deuxième enfant sera alors reçue par la stdin du troisième enfant. Les commandes stdin / stdout du processus parent ne sont pas gênées du tout.

Jusqu’à présent, ce que j’ai c’est

pipe(procpipe); parentPid = getpid(); for(i = 0; i < 3; i++) { if(getpid() == parentPid) { child[i] = fork(); if(child[i] == 0) { mynumber = i+1; } } } 

Mais à partir de là, je ne sais trop trop comment utiliser dup2 pour assigner correctement mes pipes et dans quelle section de mon code l’insérer. Il y a beaucoup d’exemples sur Google et sur ce site Web sur la façon de transférer un parent à un enfant, mais je n’en ai pas encore vu un qui me dira exactement comment connecter la sortie standard d’un enfant à la stdin d’un autre enfant.

Edit: Oublié de mentionner: supposons que toutes mes variables sont correctement initialisées. Le ‘mynumber’ est tel qu’un processus enfant sait à la création de quel numéro il s’agit, je peux donc lui donner des instructions via

 if(mynumber == whatever) 

Vous avez donc une boucle qui crée plusieurs processus enfants. Chacun de ces processus enfants utilisera deux canaux: lire du précédent et écrire au suivant. Pour configurer un tuyau pour l’extrémité de lecture, vous devez fermer l’extrémité d’écriture du tuyau et dup2 l’extrémité de lecture dans le stdin. Semblable pour le tuyau où le processus sera écrit.

 void set_read(int* lpipe) {    dup2(lpipe[0], STDIN_FILENO);    close(lpipe[0]); // we have a copy already, so close it    close(lpipe[1]); // not using this end } void set_write(int* rpipe) {    dup2(rpipe[1], STDOUT_FILENO);    close(rpipe[0]); // not using this end    close(rpipe[1]); // we have a copy already, so close it } 

Lorsque vous twigz chaque enfant, vous devez y attacher les tuyaux.

 void fork_and_chain(int* lpipe, int* rpipe) {    if(!fork())    {        if(lpipe) // there's a pipe from the previous process            set_read(lpipe); // else you may want to redirect input from somewhere else for the start        if(rpipe) // there's a pipe to the next process            set_write(rpipe); // else you may want to redirect out to somewhere else for the end // blah do your stuff // and make sure the child process terminates in here // so it won't continue running the chaining code    } } 

Avec ceci en main, vous pouvez maintenant écrire une boucle qui bifurque, attache les tuyaux, puis réutilise le tuyau de sortie comme tuyau d’entrée pour le suivant. Bien sûr, une fois que les deux extrémités d’un tuyau ont été connectées à des processus enfants, le parent ne doit pas le laisser ouvert pour lui-même.

 // This assumes there are at least two processes to be chained :) // two pipes: one from the previous in the chain, one to the next in the chain int lpipe[2], rpipe[2]; // create the first output pipe pipe(rpipe); // first child takes input from somewhere else fork_and_chain(NULL, rpipe); // output pipe becomes input for the next process. lpipe[0] = rpipe[0]; lpipe[1] = rpipe[1]; // chain all but the first and last children for(i = 1; i < N - 1; i++) {    pipe(rpipe); // make the next output pipe    fork_and_chain(lpipe, rpipe); close(lpipe[0]); // both ends are attached, close them on parent close(lpipe[1]);    lpipe[0] = rpipe[0]; // output pipe becomes input pipe    lpipe[1] = rpipe[1]; } // fork the last one, its output goes somewhere else  fork_and_chain(lpipe, NULL); close(lpipe[0]); close(lpipe[1]); 

Les bits de clôture sont très importants! Lorsque vous twigz avec un canal ouvert, il y a quatre descripteurs de fichier ouverts: deux sur le processus parent et deux autres sur le processus enfant. Vous devez fermer tous ceux que vous n'utiliserez pas. C'est pourquoi le code ci-dessus ferme toujours les extrémités non pertinentes des canaux dans les processus enfants et les deux extrémités sur le parent.

Notez également que j'accorde un traitement spécial au premier et au dernier processus, car je ne sais pas d'où proviendra l'entrée de la chaîne ni où elle ira.