【问题标题】:How do I send data in C from two children to parent using pipes?如何使用管道将 C 中的数据从两个孩子发送到父母?
【发布时间】:2016-05-22 21:50:36
【问题描述】:

我有这个任务,我必须使用 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;
}

【问题讨论】:

    标签: c pipe fork


    【解决方案1】:

    你想关闭你没有在每个子进程中使用的任何东西,尤其是父进程的写入端:

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

    否则,子进程将保持写入端打开并防止管道完全关闭,从而使您永远不会在子进程中获得 EOF。您部分地这样做了,但是由于第二个孩子已经打开了 write[PIPE_1],因此 PIPE_1 从未完全关闭。

    【讨论】:

      猜你喜欢
      • 2019-03-23
      • 1970-01-01
      • 2015-01-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多