La tuyauterie d'entrée/de sortie
Cette question découle de ma tentative de mettre en œuvre les instructions de la section:
Linux Tuyaux d'Entrée et de Sortie
Comment envoyer une simple chaîne de caractères entre deux programmes à l'aide de tuyaux?
http://tldp.org/LDP/lpg/node11.html
Ma question est, le long de la lignes de la question: Linux Tuyaux d'Entrée et de Sortie, mais plus spécifiques.
Essentiellement, je suis en train de remplacer:
/directory/program < input.txt > output.txt
à l'aide de tuyaux en C++ afin d'éviter d'utiliser le disque dur. Voici mon code:
//LET THE PLUMBING BEGIN
int fd_p2c[2], fd_pFc[2], bytes_read;
//"p2c" = pipe_to_child, "pFc" = pipe_from_child (see above link)
pid_t childpid;
char readbuffer[80];
string program_name;//<---- includes program name + full path
string gulp_command;//<---- includes my line-by-line stdin for program execution
string receive_output = "";
pipe(fd_p2c);//create pipe-to-child
pipe(fd_pFc);//create pipe-from-child
childpid = fork();//create fork
if (childpid < 0)
{
cout << "Fork failed" << endl;
exit(-1);
}
else if (childpid == 0)
{
dup2(0,fd_p2c[0]);//close stdout & make read end of p2c into stdout
close(fd_p2c[0]);//close read end of p2c
close(fd_p2c[1]);//close write end of p2c
dup2(1,fd_pFc[1]);//close stdin & make read end of pFc into stdin
close(fd_pFc[1]);//close write end of pFc
close(fd_pFc[0]);//close read end of pFc
//Execute the required program
execl(program_name.c_str(),program_name.c_str(),(char *) 0);
exit(0);
}
else
{
close(fd_p2c[0]);//close read end of p2c
close(fd_pFc[1]);//close write end of pFc
//"Loop" - send all data to child on write end of p2c
write(fd_p2c[1], gulp_command.c_str(), (strlen(gulp_command.c_str())));
close(fd_p2c[1]);//close write end of p2c
//Loop - receive all data to child on read end of pFc
while (1)
{
bytes_read = read(fd_pFc[0], readbuffer, sizeof(readbuffer));
if (bytes_read <= 0)//if nothing read from buffer...
break;//...break loop
receive_output += readbuffer;//append data to string
}
close(fd_pFc[0]);//close read end of pFc
}
Je suis absolument sûr que les chaînes ci-dessus sont correctement initialisé. Cependant, deux choses se produisent qui ne font pas de sens pour moi:
(1) Le programme que je suis en exécution de rapports que le "fichier d'entrée est vide." Depuis que je ne suis pas d'appeler le programme avec "<" il ne faut pas s'attendre à un fichier d'entrée. Au lieu de cela, il devrait attendre de la saisie au clavier. En outre, il convient de lire le texte contenu dans "gulp_command."
(2) Le programme de rapport (fourni par la sortie standard) s'affiche sur le terminal. C'est bizarre parce que le but de cette tuyauterie est de transférer stdout à ma chaîne "receive_output." Mais comme il apparaît sur l'écran, cela m'indique que l'information n'est pas transmis correctement par le tuyau de la variable. Si j'en œuvre à la fin de l'instruction if,
cout << receive_output << endl;
Je ne reçois rien, comme si la chaîne est vide. J'apprécie toute l'aide que vous pouvez me donner!
EDIT: Précisions
Mon programme communique avec un autre programme à l'aide de fichiers texte. Mon programme écrit dans un fichier texte (par ex. input.txt), qui est lu par le programme externe. Ce programme permet ensuite de produit output.txt, qui est lu par mon programme. C'est donc quelque chose comme ceci:
my code -> input.txt -> program -> output.txt -> my code
Donc, mon code utilise actuellement,
system("program < input.txt > output.txt");
Je veux remplacer ce processus à l'aide de tuyaux. Je veux passer mon entrée comme entrée standard du programme, et d'avoir mon code lire la sortie standard de ce programme dans une chaîne de caractères.
/directory/program <input.txt >output.txt
avec quelque chose à l'aide de tuyaux afin d'éviter les accès au système de fichiers. Mais vous avez "besoin" de multiples procédés pour rendre l'utilisation de tuyaux à fait raisonnable. (Vous utiliser des tubes en un seul processus, mais il n'a pas de sens en général.) Donc, vous pourriez avoir /directory/program1 <input.txt | /directory/program2 >output.txt
; de bon sens (et vous pourriez déjà avoir utilisé /directory/program1 <input.txt >intermediate.txt; /directory/program2 <intermediate.txt >output.txt
). Veuillez préciser votre intention.Bon point. J'ai édité la question.
Comme un supplément de précisions, mon objectif est essentiellement la même que la question en: stackoverflow.com/questions/1734932/... qui vous avez répondu précédemment (grande réponse par la voie).
comment ferions-nous pour exécuter ce code si je veux faire la même chose, mais pour deux enfants de processus? sens de l'envoi et de la réception de chaînes entre deux processus enfant ignorant le parent.
Je n'ai jamais essayé avant. Malheureusement je ne peux pas vous donner des conseils en ce moment.
OriginalL'auteur Eric Inclan | 2013-07-07
Vous devez vous connecter pour publier un commentaire.
Votre principal problème, c'est que vous avez des arguments à
dup2()
inversée. Vous devez utiliser:J'ai dupé dans l'erreur de lecture, ce que vous avez écrit comme OK jusqu'à ce que j'ai mis vérification des erreurs sur le code et a obtenu des valeurs inattendues de la
dup2()
appels, qui m'a dit que ce était la difficulté. Quand quelque chose va mal, insérer les contrôles d'erreur vous lésiné sur les avant de.Vous également de ne pas assurer la terminaison null de la lecture de données à partir de l'enfant; ce code n'.
Code de travail (diagnostic), à l'aide de
cat
que le plus simple possible", d'autres de la commande":Exemple de sortie:
Notez que vous aurez besoin d'être prudent afin de s'assurer que vous n'obtenez pas dans l'impasse avec votre code. Si vous avez un strict protocole synchrone (de sorte que le parent écrit un message et lit une réponse en lock-step), vous devez être bien, mais si le parent est d'essayer d'écrire un message qui est trop gros pour rentrer dans le tuyau de l'enfant lorsque l'enfant est d'essayer d'écrire un message qui est trop gros pour rentrer dans le tuyau à la maison mère, alors chacun sera bloqué par écrit lors de l'attente pour les autres à lire.
comment ferions-nous pour exécuter ce code si je veux faire la même chose, mais pour deux enfants de processus? sens de l'envoi et de la réception de chaînes entre deux processus enfant ignorant le parent.
il dépend en partie de la façon dont les enfants vont communiquer, et sur ce que le processus parent fera après le démarrage de la deux enfants. Il y a plusieurs façons de traiter avec elle. Une option est de simplement demander au parent avec une fourchette avant de faire tout le code ci-dessus, et le processus parent de cette fourchette peut quitter ou d'attente ou de continuer avec d'autres travaux, alors que le processus de l'enfant manipule le code comme ci-dessus. Sinon, le processus parent met en place les deux tuyaux, fourches à deux fois, et chaque enfant trie ses propres plomberie, tandis que la mère ferme les quatre descripteurs de fichier pour les deux tuyaux et reprend son chemin.
Ya j'ai fait exactement la deuxième méthode que vous l'avez suggéré, j'ai juste simplement faire une pipe et deux fourchettes une pour child_a autres pour child_b, si le pid_child_a est égale à zéro de l'écriture sur le tuyau d'autre si pid_child_b est de zéro, il lit et imprime la valeur du tampon, le problème est que lorsque j'exécute la première fois, il fonctionne très bien, mais la deuxième fois je l'exécuter imprime rien. Parfois, quand je nettoie le projet ou pour faire de l'édition donne à nouveau de sortie correct, mais là encore, commence à imprimer rien la deuxième et ainsi de suite.
et aussi, si je le lance en mode debug, il donne de bons résultats à chaque fois
OriginalL'auteur Jonathan Leffler
Il semble que vous êtes à la recherche pour coprocesses. Vous pouvez les programmer en C/C++, mais depuis qu'ils sont déjà disponibles dans l' (bash) shell, plus facile à utiliser la coquille, droite?
D'abord démarrer le programme externe avec le
coproc
builtin:La
coproc
démarre le programme en arrière-plan et enregistre les descripteurs de fichiers pour communiquer avec elle dans un tableau de variable d'environnement. Maintenant, vous avez juste besoin de commencer votre programme de le connecter à ces descripteurs de fichiers:Les descripteurs sont reliés à des tuyaux dans ce cas, pas de fichiers. Aussi, vous pouvez exécuter un script bash des milliers de fois, trop.
OriginalL'auteur Joni
OriginalL'auteur Priyanshu Shukla