pid_t kids[argc];
int childCount = argc - 1;
int fd[2];
/* create the pipe*/
if (pipe(fd) == -1) {
fprintf(stderr ,"Pipe failed");
return 1;
for(i=0; i < childCount; i++) {
kids[i] = fork();
if(kids[i] < 0){
//fork fail
}
else if(kids[i] == 0) {
/* child process */
sum = max + min;//sum and dif are results from each child process
dif = max - min;
/* close the unused end of pipe, in this case, the read end */
close(fd[READ_END]);
/* write to the pipe */
write(fd[WRITE_END], &sum, sizeof(sum));
write(fd[WRITE_END], &dif, sizeof(dif));
/* close write end */
close(fd[WRITE_END]);
exit(0);
}
else {
waitpid(kids[i], &status, 0);
close(fd[WRITE_END]);
read(fd[READ_END], &sum, sizeof(float));
read(fd[READ_END], &dif, sizeof(float));
close(fd[READ_END]);
}
}
Above are the code, which is simplified a little bit.
What I want to do is waiting for any child to finish and processing its data then repeating this untill all children are finished.
Can someone tell me how to pipe the data generated by the children to the parent?
You didn't mention what the problem with your current code is, and the code you showed doesn't compile, so I can only guess that this is an approximation of your real code.
Nevertheless, here's what caught my eye:
You never close the body of if (pipe(fd) == -1)
before the loop, which means that the loop is part of the if
body. This is probably not what you want, although I'm not sure if it was a typo / copy paste error. Maybe in the real code you do close the if
.
The code for the parent process is wrong: because it is running inside the for
loop, you repeatedly call close(2)
on the pipe's write and read end. This will cause close(2)
to return an error (EBADF
), which you blatantly ignore, upon the second iteration of the loop. Also in the second iteration, the forked child will attempt to close the read channel of a pipe that doesn't exist anymore (because the parent process from where we just forked closed both ends in the previous iteration before forking again), and then it attempts to write to a pipe that doesn't exist.
To fix it, you have to make sure that the parent doesn't close the pipe until every child is done with it. Do not close(2)
in the parent inside the loop; instead, do it after the loop:
for(i=0; i < childCount; i++) {
kids[i] = fork();
if(kids[i] < 0){
//fork fail
}
else if(kids[i] == 0) {
/* child process */
sum = max + min;//sum and dif are results from each child process
dif = max - min;
/* close the unused end of pipe, in this case, the read end */
close(fd[READ_END]);
/* write to the pipe */
write(fd[WRITE_END], &sum, sizeof(sum));
write(fd[WRITE_END], &dif, sizeof(dif));
/* close write end */
close(fd[WRITE_END]);
exit(0);
}
else {
waitpid(kids[i], &status, 0);
read(fd[READ_END], &sum, sizeof(float));
read(fd[READ_END], &dif, sizeof(float));
}
}
close(fd[READ_END]);
close(fd[WRITE_END]);
Since you wait for each child to terminate in the loop, it is guaranteed that you will not close the pipe when there is still an active writer.