'Pipe with multiple child process
I want to create N processes from one parent and this child processes have to read that parent write, but what i have only the first process reads correctly:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
pid_t pid;
int fd[2];
char buff[50];
char str[] = "Hello";
if(pipe(fd) == -1){
fprintf(stderr, "pipe Failed");
return 1;
}
for(int num_process = 0; num_process < 3; num_process++){
pid = fork();
if(pid < 0){
perror("Error");
exit(1);
}
if(pid == 0){ //child code
printf("Child %i (pid= %i)\n", num_process, getpid());
close(fd[1]);
read(fd[0], buff, sizeof(buff)); //read from pipe
printf("Read child = %s\n", buff);
close(fd[0]);
exit(0);
}
else{//parent
printf("Im parent %i\n",getpid());
close(fd[0]);
write(fd[1], str,strlen(str)+1);
printf("Parent send %s\n", str);
close(fd[1]);
for(int num_process = 0; num_process < 3; num_process++){
wait(NULL);
}
}
}
return 0;
}
output:
Im parent 5863
Parent send Hello
Child 0 (pid= 5864)
Read child = Hello
Im parent 5863
Parent send Hello
Child 1 (pid= 5865)
Read child =
Im parent 5863
Parent send Hello
Child 2 (pid= 5866)
Read child =
Solution 1:[1]
read(fd[0], buff, sizeof(buff)); //read from pipe printf("Read child = %s\n", buff);
If you did check the return value of read
(as you always should) you would've seen that the 2nd and 3rd time it returns -1 and sets errno
to EBADF
. That's because you've already closed the read end of the pipe in the first iteration of the loop, in the "parent" part, here:
printf("Im parent %i\n",getpid()); close(fd[0]);
The same thing with the write
following it:
write(fd[1], str,strlen(str)+1); printf("Parent send %s\n", str); close(fd[1]);
fd[1]
will be closed in the 1st iteration of the loop, and the write
will fail with EBADF
the 2nd and 3rd time.
Solution 2:[2]
the following proposed code:
- handles each child separately
- performs the desired functionality
- incorporates the comments to the OPs question
- caveat: the closing of the pipe ends is somewhat careless in the proposed code
and now the proposed code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define MAX_CHILDREN 3
int main( void )
{
pid_t pid;
int fd[2];
char str[] = "Hello";
for(int num_process = 0; num_process < MAX_CHILDREN; num_process++)
{
if(pipe(fd) == -1)
{
perror( "pipe Failed" );
continue;
}
pid = fork();
if(pid < 0)
{
perror("fork failed");
exit(1);
}
if(pid == 0)
{ //child code
char buff[50];
printf("Child %i (pid= %i)\n", num_process, getpid());
close(fd[1]);
if ( read( fd[0], buff, sizeof(buff)) <= 0) //read from pipe
{
perror( "read failed" );
exit( EXIT_FAILURE );
}
printf("Read child = %s\n", buff);
exit(0);
}
else{//parent
printf("Im parent %i\n",getpid());
close(fd[0]);
write(fd[1], str,strlen(str)+1);
printf("Parent send %s\n", str);
wait(NULL);
}
}
return 0;
}
A typical run of the code results in:
Im parent 26451
Parent send Hello
Child 0 (pid= 26452)
Read child = Hello
Im parent 26451
Parent send Hello
Child 1 (pid= 26453)
Read child = Hello
Im parent 26451
Parent send Hello
Child 2 (pid= 26454)
Read child = Hello
Solution 3:[3]
Pipes are end to end, what you are trying to do is a chat.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | mosvy |
Solution 2 | user3629249 |
Solution 3 | Punisher |