Linux 具有多个子进程的管道

Linux 具有多个子进程的管道,linux,c,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 pi

我想从一个父进程创建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;
}
如果您确实检查了
read
的返回值(您总是应该这样做),您会看到第二次和第三次它返回-1并将
errno
设置为
EBADF
。这是因为在循环的第一次迭代中,在“父”部分,您已经关闭了管道的读取端,如下所示:

下面的
write
也一样:


fd[1]
将在循环的第一次迭代中关闭,
写入将在
EBADF
第二次和第三次失败。

以下建议的代码:

#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;
}
  • 分别处理每个孩子
  • 执行所需的功能
  • 纳入对老年退休金计划问题的评论
  • 警告:在建议的规范中,关闭管端有点粗心
  • 现在建议的守则是:

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

    OT:关于:
    int main(int argc,char*argv[]){
    当未使用
    main()
    的参数时,使用签名:
    int main(void)
    OT:为了便于阅读和理解:1)一致地缩进代码。在每个左大括号之后缩进{.Unindent在每个右大括号之前缩进}'.建议每个缩进级别为4个空格。OT:发布的代码包含一些“魔法”数字。例如,3。“魔法”数字使代码更难理解、调试等。建议使用
    enum
    语句或
    #define
    语句为该“魔法”数字指定一个有意义的名称,然后在整个c语言中使用该有意义的名称关于:
    if(pid<0){perror(“Error”);exit(1);
    这将使父进程在一个或多个子进程仍在运行时退出。(一个创建僵尸进程的便捷工具。)建议在调用
    exit()之前为每个子进程插入一个
    wait()
    关于:
    for(int num_process=0;num_process<3;num_process++){wait(NULL);}
    此循环位于创建子进程的循环内。应该在创建所有子进程之后。因此,关闭管道的目的是什么?您应该只在子进程中执行
    关闭(fd[1])
       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]);
    
    #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