具有多个子进程的管道

时间:2018-12-05 23:34:40

标签: linux c

我想从一个父进程创建N个进程,而这个子进程必须读取该父进程的写操作,但是我只有第一个进程才能正确读取:

#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;
}

输出:

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 = 

2 个答案:

答案 0 :(得分:1)

read(fd[0], buff, sizeof(buff)); //read from pipe
printf("Read child = %s\n", buff);

如果您确实检查了read的返回值(如往常一样),您会发现它第二次和第三次返回-1并将errno设置为EBADF 。那是因为您已经在循环的第一次迭代中的“父”部分中关闭了管道的读取端:

   printf("Im parent %i\n",getpid());
   close(fd[0]);

后面跟着write的是同一件事:

   write(fd[1], str,strlen(str)+1);
   printf("Parent send %s\n", str);
   close(fd[1]);

fd[1]将在循环的第1次迭代中关闭,而write将在EBADF第2次和第3次失败。

答案 1 :(得分:1)

以下建议的代码:

  1. 分别处理每个孩子
  2. 执行所需的功能
  3. 将评论纳入OP问题
  4. 腔室:在建议的代码中管端的闭合有点粗心

现在是建议的代码:

#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;
}

典型的代码运行结果为:

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