I'm trying to properly connect three processes in order to allow inter-process communication between them. I have one process, scanner, which takes the parent's STDIN and then processes the words within the stream. If a word length is odd, it sends it to one process, if it is even, it sends it to another. These processes should take in these words via STDIN (I assume) and then output some info back to the scanner process via STDOUT. The STDOUT of even/odd should be redirected to scanner, which will then read (using read) and then output/process the words. It's an academic exercise, not a practical one. Here's what a picture of it would look like:
Here's what my code currently looks like. The problem is I'm not exactly sure what to dup and what to close. Once I figure that out I should be good to go! Any advice would be appreciated.
File descriptors:
int scannertoeven[2]; int scannertoodd[2];
int eventoscanner[2]; int oddtoscanner[2];
//Pipe stuff here (ommitted)
Code:
//Create the child processes
if ((scanner_pid = fork()) == 0) {
//We need the scanner pid so even and odd can send signals to it
char pidofparent[sizeof(getpid())];
sprintf(pidofparent, "%i", getpid());
//Even stuff
if ((even_pid = fork()) == 0) {
close(scannertoodd[0]); close(scannertoodd[1]);
close(oddtoscanner[0]); close(oddtoscanner[1]);
//Not sure which ones to close
close(scannertoeven[0]); close(scannertoeven[1]);
close(eventoscanner[0]); close(eventoscanner[1]);
//Correct?
close(STDIN_FILENO);
dup2(scannertoeven[0], STDIN_FILENO);
close(STDOUT_FILENO);
dup2(eventoscanner[1], STDOUT_FILENO);
if(execl("./evenodd", "even", pidofparent, NULL ) == -1) {
printf("execl Error!");
exit(1);
}
//Odd Stuff
} else if ((odd_pid = fork()) == 0){
close(scannertoeven[0]); close(scannertoeven[1]);
close(eventoscanner[0]); close(eventoscanner[1]);
//Not sure which ones to close
close(scannertoodd[0]); close(scannertoodd[1]);
close(oddtoscanner[0]); close(oddtoscanner[1]);
//Correct?
close(STDIN_FILENO);
dup2(scannertoodd[0], STDIN_FILENO);
close(STDOUT_FILENO);
dup2(oddtoscanner[1], STDOUT_FILENO);
if(execl("./evenodd", "odd", pidofparent, NULL ) == -1) {
printf("execl Error!");
exit(1);
}
//Actual Scanner
} else {
// Not sure which ones to close- this is very wrong
close(scannertoeven[0]); close(scannertoeven[1]);
close(eventoscanner[0]); close(eventoscanner[1]);
close(scannertoodd[0]); close(scannertoodd[1]);
close(oddtoscanner[0]); close(oddtoscanner[1]);
//Not sure what to dup either
dup2(scannertoodd[1], STDOUT_FILENO);
dup2(scannertoeven[1], STDOUT_FILENO);
if(execl("./scanner", "scanner", stoeven, stoodd, eventos, oddtos, NULL ) == -1) {
printf("execl Error!");
exit(1);
}
//Wait twice here, or three times in main?
waitpid(odd_pid, &status2, 0);
waitpid(even_pid, &status3, 0);
}
//Main
} else {
//Close Pipes
close(scannertoodd[0]); close(scannertoeven[0]); close(eventoscanner[0]); close(oddtoscanner[0]);
close(scannertoodd[1]); close(scannertoeven[1]); close(eventoscanner[1]); close(oddtoscanner[1]);
//Wait for children to finish
waitpid(scanner_pid, &status1, 0);
printf("Done\n");
}
Not sure about the logic. But the way you use dup2 is not right.
The following code in the "Even" process:
close(STDIN_FILENO);
dup2(scannertoeven[0], STDIN_FILENO);
close(STDOUT_FILENO);
dup2(eventoscanner[1], STDOUT_FILENO);
should be:
dup2(scannertoeven[0], STDIN_FILENO);
// You should close scannertoeven[0], not STDIN. After this dup2, the even
// process will receive input from scannertoeven[0]
close(scannertoeven[0]);
// Note the the scannertoeven[0] is not "really" closed, just that the file
// is "attached" to STDIN
dup2(eventoscanner[1], STDOUT_FILENO);
// Same as above. After this dup2, all the even process's output will go
// to eventoscanner[1]
close(eventoscanner[1]);
The same as the "Odd" process.
Here is an example of dup2, for your reference.