Warten auf Kind-Prozesse
-
Hallo,
ich möchte, dass 2 Kind-Prozesse erzeugt werden, welche jeweils auf Benutzereingaben warten. Was eingegeben wurde soll dann an den Parent Prozess über die Pipe zurückgesendet werden. Dieser soll dann die beiden Meldungen der Kinder in der richtigen Reihenfolge ausgeben.
Mein Versuch:void main() { char inbuf[MSGSIZE]; char *ausgabe[2]; char *msg; int p[2]; pid_t pid; int child = 0; pid= fork(); for (child=0;child<2; child++){ if (pid == -1 ) { perror("fork call"); } else if (pid == 0 ) { printf ("Child %d von PPID %d mit der PID %d.\n",child, getppid(), getpid ()); msg=(char)fgetc(stdin); write(p[1], msg, MSGSIZE); exit(0); } else if (pid > 0){ printf ("Parent von %d mit der PID %d.\n",pid, getpid ()); wait((int*)0); read(p[0], inbuf, MSGSIZE); ausgabe[child]=inbuf; pid = fork(); } } printf("Child 1 sagt %s: \n", ausgabe[0]); printf("Child 2 sagt %s: \n", ausgabe[1]); exit(0); }
Der untere Teil außererhalb der Schleife wird aber immer doppelt ausgegeben und ich verstehe nicht woran das liegt. Wie kann ich das ändern?
Vieelen Dank!
-
Abgesehen von diesem Problem, sieht meine Ausgabe übrigens so aus
:
Child 1 sagt X���:
Child 2 sagt X���:
Child 1 sagt X���:
Child 2 sagt X���:
Wäre schön wenn mir zu diesem (wahrscheinlich) Cast Problem auch noch jemand einen Tip geben könnte.
-
int main
! Keinvoid main
! http://c-plusplus.net/forum/viewtopic-var-t-is-39346.htmlDie Ausgabe sieht so aus, weil du nicht beachtet hast, dass C-Strings immer 0-Terminiert sind. Du liest ein Zeichen ein und schreibst das in die Pipe und liest es dann aus und versuchst es als String auszugeben, obwohl du keine 0-Terminierung hast.
Die Ausgabe erfolgt zweimal, weil zwei Prozesse die Ausgabe tätigen. Überleg dir mal was genau passiert, wenn
child == 1
ist (spoiler: fork wird aufgerufen und die Schleife vor dem nächsten Durchlauf beendet. Sprich die Bedingungen werden für das fork gar nicht mehr ausgewertet)
-
vieeelen Dank! Es geht schonmal voran.
Mein Code sieht jetzt folgendermaßen aus:
int main() { char inbuf[MSGSIZE]; char msg[MSGSIZE]; char *ausgabe[2]; int p[2],i; pid_t pid; int child = 0; pipe(p); pid= fork(); for (child=0;child<2; child++){ if (pid == -1 ) { perror("fork call"); exit(-1); } else if (pid == 0 ) { printf ("Child %d von PPID %d mit der PID %d.\n",child, getppid(), getpid ()); scanf("%s",msg); write(p[1], msg, MSGSIZE); exit(0); } else if (pid > 0){ printf ("Parent von %d mit der PID %d.\n",pid, getpid ()); wait((int*)0); read(p[0], inbuf, MSGSIZE); ausgabe[child] = inbuf; if(child<1){pid = fork();} } } printf("Child 0 sagt: %s \n", ausgabe[0]); printf("Child 1 sagt: %s \n", ausgabe[1]); exit(0); }
Durch die if Abfrage konnte ich das zweite unnötige fork() wohl vermeiden. Ist es das was Du meintest?
Die Ausgabe erfolgt jetzt auch nur noch einmal.
Allerdings "sagen" jetzt beide Kinder das gleiche. Und zwar nur das was im zweiten Child Prozess eingegeben wurde. Woran liegt das denn? Wird ausgabe[0] irgendwo überschrieben? Ich finde den Fehler nichtParent von 7669 mit der PID 7668.
Child 0 von PPID 7668 mit der PID 7669.
asd
Parent von 7679 mit der PID 7668.
Child 1 von PPID 7668 mit der PID 7679.
we
Child 0 sagt: we
Child 1 sagt: we
-
ausgabe[child] = inbuf;
hier übergibst du pointer auf inbuf auf ausgabe[child].
Um Fehler zu beheben musst du:
1. der ausgabe[child] platz allokieren (realloc oder anderes) oder am anfang sagen (siehe Beispiel)
2. den inhalt kopieren (stichwort memcpy (Beispiel) bzw memmov)int main() { char inbuf[MSGSIZE]; char msg[MSGSIZE]; char *ausgabe[2]; char ausg1[MSGSIZE]; char ausg2[MSGSIZE]; ausgabe[0] = ausg1; ausgabe[1] = ausg2; int p[2],i; pid_t pid; int child = 0; pipe(p); pid= fork(); for (child=0;child<2; child++){ if (pid == -1 ) { perror("fork call"); exit(-1); } else if (pid == 0 ) { printf ("Child %d von PPID %d mit der PID %d.\n",child, getppid(), getpid ()); scanf("%s",msg); write(p[1], msg, MSGSIZE); exit(0); } else if (pid > 0){ printf ("Parent von %d mit der PID %d.\n",pid, getpid ()); wait((int*)0); read(p[0], inbuf, MSGSIZE); memcpy(ausgabe[child], inbuf, strlen(inbuf)+1); if(child<1){pid = fork();} } } printf("Child 0 sagt: %s \n", ausgabe[0]); printf("Child 1 sagt: %s \n", ausgabe[1]); exit(0); }
und schon hast du folgende Ausgabe:
Child 0 von PPID 10338 mit der PID 10339. Parent von 10339 mit der PID 10338. abc Child 1 von PPID 10338 mit der PID 10345. Parent von 10345 mit der PID 10338. 123 Child 0 sagt: abc Child 1 sagt: 123