如何使用管道将C中的数据从两个子节点发送到父节点?

时间:2016-05-22 21:50:36

标签: c pipe fork

我有这个任务,我必须使用fork创建两个孩子。父母必须向这些孩子发送一些信件并收回一个号码。沟通必须使用管道完成。 我无法弄清楚的是,为什么我的代码设法将信件发送给孩子,但随后却无所事事。起初我以为是因为waitpid()调用,但似乎并非如此。令我感到困惑的是,如果我停止阅读其中一个子进程并只发送一个随机数,其他一切都按预期工作。

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>

#define PIPE_1 0 // write to 1st child
#define PIPE_2 1 // write to parent from 1st child
#define PIPE_3 2 // write to 2nd child
#define PIPE_4 3 // write to parent from 2nd child

int main()
{
    pid_t p1, p2;
    int pipes[4][2];
    FILE *read[4], *write[4];

    int k;
    for (k = 0; k < 4; k++){
        if (-1 == pipe(pipes[k]) ){
            perror("Error creating pipe");
            exit(k+1);
        }
        read[k] = fdopen(pipes[k][0], "r");
        write[k] = fdopen(pipes[k][1], "w");
    }

    if (-1 == (p1 = fork()) ){
        perror("Error, failed to fork first child");
        exit(5);
    }

    if (p1 == 0){
        // 1st child
        fclose(write[PIPE_1]);
        int caseChange = 0;
        char c;
        while( fscanf(read[PIPE_1], "%c", &c) != EOF){
            if (c >= 97 && c <= 122){
                    c -= 32;
                    caseChange++;
            }
            printf("[Process (%d)]: %c\n", getpid(), c);
        }
        fclose(read[PIPE_1]);

        fclose(read[PIPE_2]);
        fprintf(write[PIPE_2],"%d",caseChange);
        fflush(write[PIPE_2]);
        fclose(write[PIPE_2]);  
    }
    else{
        if (-1 == (p2 = fork()) ){
            perror("Error, failed to fork second child");
            exit(6);
        }

        if (p2 == 0){
            // 2nd child
            fclose(write[PIPE_3]);
            int caseChange = 0;
            char c;
            while( fscanf(read[PIPE_3], "%c", &c) != EOF){
                if (c >= 97 && c <= 122){
                    c -= 32;
                    caseChange++;
                }
                printf("[Process (%d)]: %c\n", getpid(), c);
            }
            fclose(read[PIPE_3]);

            fclose(read[PIPE_4]);
            fprintf(write[PIPE_4],"%d",caseChange);
            fflush(write[PIPE_4]);
            fclose(write[PIPE_4]);  
        }
        else{
            // Parent
            //char *string = (char*) malloc(100);
            char string[100];
            scanf("%s", string);
            int i;

            int readCaseChange, caseChange = 0;

            fclose(read[PIPE_1]);
            for (i = 0; i < strlen(string); i+=2){
                fprintf(write[PIPE_1],"%c",string[i]);
                fflush(write[PIPE_1]);
            }
            fclose(write[PIPE_1]);

            fclose(read[PIPE_3]);
            for (i = 1; i < strlen(string); i+=2){
                fprintf(write[PIPE_3],"%c",string[i]);
                fflush(write[PIPE_3]);
            }
            fclose(write[PIPE_3]);

            waitpid(p1, NULL, 0);
            fclose(write[PIPE_2]);
            fscanf(read[PIPE_2], "%d", &readCaseChange);
            fclose(read[PIPE_2]);
            caseChange += readCaseChange;

            waitpid(p2, NULL, 0);
            fclose(write[PIPE_4]);
            fscanf(read[PIPE_4], "%d", &readCaseChange);
            fclose(read[PIPE_4]);
            caseChange += readCaseChange;

            printf("%d\n", caseChange);
            fflush(stdout);
        }
    }
    return 0;
}

1 个答案:

答案 0 :(得分:1)

您希望关闭每个孩子中没有使用的任何内容,尤其是父进程的作者方:

// 1st child
fclose(write[PIPE_1]);
fclose(write[PIPE_3]);

// 2nd child
fclose(write[PIPE_1]);
fclose(write[PIPE_3]);

否则,子进程将使编写器端保持打开状态并防止管道完全关闭,从而使其无法在子进程中获得EOF。你部分这样做,但是因为第二个孩子写了[PIPE_1],所以PIPE_1从未完全关闭。