De la Pipe, de la Fourche, et Exec - Communication dans les Deux sens Entre le Parent et l'Enfant
Une affectation dans mes Systèmes d'Exploitation de la classe me demande de construire un processus binaire de l'arbre de manière récursive par l'appel exec sur le même programme. L'objectif est de diviser certains arbitraire des tâches dans des processus séparés. Le parent doit communiquer avec les enfants, et les enfants avec le parent uniquement via sans nom tuyaux. L'idée est que le parent envoie à chaque enfant la moitié de l'ouvrage et cela continue récursivement jusqu'à ce qu'un cas de base est respectée lorsque la longueur de la chaîne est passée à chaque enfant est <= 2. Ensuite, l'enfant traite ces données et envoie les résultats à la maison mère à travers des tuyaux.
Pour obtenir une meilleure compréhension de la façon dont les deux sens de la communication travaille avec des tuyaux en c j'ai créé le programme simple avant de passer à l'attribution. Le parent ne lit jamais les données du processus enfant. J'attends la sortie...
parent ou d'un message reçu: test
Au lieu de cela, quand j'ai l'impression que je reçois...
parent ou d'un message reçu:
Il semble que le buff est vide et pas de la lecture de l'enfant. Quelqu'un peut-il expliquer ce que je fais mal et/ou de la manière standard de
- écrit à exec avais de l'enfant du parent
- lecture du parent dans exec avais enfant
- rédaction de retour à parent de exec avais enfant
- lecture de exec avais de l'enfant dans le parent
Je suis obligé d'utiliser exec(), pipe(), fork(). Merci.
/**
* *********************************
* two_way_pipes.c
* *********************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define PARENT_READ read_pipe[0]
#define PARENT_WRITE write_pipe[1]
#define CHILD_WRITE read_pipe[1]
#define CHILD_READ write_pipe[0]
#define DEBUGGING 1
int main(int argc, char **argv) {
char buff[5];
//in the child process that was exec'd on the orginal call to two_way_pipes
if(argc == 2) {
read(STDIN_FILENO, buff, 4); //this should read "test" from stdin
buff[4] = '\0';
fprintf(stdout, "%s\n", buff); //this should right "test" to stdout and be read by the parent process
//int the root process, the original call to two_way_pipes with no args
} else {
int pid;
int read_pipe[2];
int write_pipe[2];
pipe(read_pipe);
pipe(write_pipe);
pid = fork();
//parent process
if(pid > 0) {
close(CHILD_READ);
close(CHILD_WRITE);
write(PARENT_WRITE, "test", 4); //attempting to write this to the child
struct timeval tv;
fd_set readfds;
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(PARENT_READ, &readfds);
select(PARENT_READ + 1, &readfds, NULL, NULL, &tv);
if(FD_ISSET(PARENT_READ, &readfds)) {
read(PARENT_READ, buff, 4); //should read "test" which was written by the child to stdout
buff[4] = '\0';
close(PARENT_READ);
close(PARENT_WRITE);
fprintf(stderr, "in parent | message received: %s\n", buff); //"test" is not in buff
}
//child process
} else if(pid == 0) {
close(PARENT_READ);
close(PARENT_WRITE);
dup2(CHILD_READ, STDIN_FILENO);
dup2(CHILD_WRITE, STDOUT_FILENO);
close(CHILD_READ);
close(CHILD_WRITE);
char *argv2[] = {"some random arg to make sure that argc == 2 in the child", NULL};
execvp("two_way_pipes", argv2);
_exit(0);
//error forking child process
} else {
fprintf(stderr, "error forking the child\n");
}
}
}
Mise à jour
Basé sur Jonathon de réponse, j'ai modifié le arg2 tableau transmis dans execvp...
char *argv2[] = {"two_way_pipes", "1", NULL};
execvp("two_way_pipes", argv2);
Cela n'a pas de résoudre le problème. La mère n'était toujours pas en mesure de lire "test" de retour de la part du client. Toutefois, en réponse à Jonathon la réponse de William le commentaire que j'ai commencé à bidouiller mon exec appel et pour une raison de le changer pour la ligne ci-dessous montrent travaillé.
execl("two_way_pipes", "two_way_pipes", "1", NULL);
Je serai heureux d'accepter toutes les réponses pour expliquer pourquoi la execvp appel ne fonctionne pas mais le execl appel n'.
perror( "execvp" )
Merci William. J'ai remplacé le _exit(0) avec perror("execvp"). Ce message d'erreur jamais imprimé, mais j'ai commencé à bidouiller mon exec appel et pour une raison quelconque modification de l'appel à execl("two_way_pipes", "two_way_pipes", "1", NULL); correction du problème.
Ce code, par conséquent, manque de tester le résultat de l'appel système. Pas fait faire de test et de débogage dur et le programme faible. Veuillez voir ma réponse.
OriginalL'auteur Anthony Jack | 2013-10-04
Vous devez vous connecter pour publier un commentaire.
Outre le problème mentionné par Jonathon Reinhart, plus probablement, l'appel à
execv()
échoue.Pour tester cette modifiez ces lignes
être
S'attendre à recevoir
Pour résoudre ce changement
être
Également si l'enfant n'était pas
exec*()
ed alors cette ligneéchoue et, à son tour
buff
n'est pas initialisé et, par conséquent, cette ligneprovoque un comportement indéterminé.
Pour corriger cela au moins correctement initialiser
buff
en changeantêtre
Désolé à ce sujet. Je pense que si je ont été nommés Anthany gens souvent mal orthographié aussi 🙂
Sry Jonathon, corrigé.
OriginalL'auteur alk
La première entrée dans votre
argv2
doit être le nom de l'exécutable (tout comme la réception de vosargv[0]
.De la
execvp
de la page de manuel:OriginalL'auteur Jonathon Reinhart
Que Jonathon Reinhart dit que vous devriez changer cette ligne:
:
alors qu'il fonctionne comme prévu:
Dans votre programme que vous avez écrit "two_way_pipes" mais il n'est pas dans votre CHEMIN si vous avez vraiment besoin de l'appoint ./donc, argv[0] est alors ("./two_way_pipes").
OriginalL'auteur Jerry Jacobs