简体   繁体   中英

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 = 
 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.

the following proposed code:

  1. handles each child separately
  2. performs the desired functionality
  3. incorporates the comments to the OPs question
  4. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM