C语言中父母与两个孩子之间的管道

同步

我正在尝试编写一个使用管道在父代和两个子代之间发送信息的C程序。该程序的目标是为字符串实现类似于合并排序的功能。我先读取字符串的数量,然后再读取字符串。字符串在两个子项之间进行划分,递归直到每个子项只有一个字符串。我必须重定向孩子的标准输入以从父标准输出中读取。

出于某种原因,所有孩子都不比第一个字符串读更多。我该如何解决这个问题?

int main(int argc, char * argv[]) {
    int nrrows = 0;
    char * buffer = NULL;
    size_t n = 0;
    getline(&buffer, &n, stdin);
    char * endptr;
    nrrows = strtol(buffer, &endptr, 10);

    char rows[nrrows][MAX_LEN];
    int i = 0;
    n = 0;
    while(i < nrrows) {
        char * row = NULL;
        getline(&row, &n, stdin);   
        strcpy(rows[i], row);
        i++;
    }

    if(nrrows == 1) {
        fprintf(stderr, "%s", rows[0]);
        return 0;   
    }

    int fdcp1[2];
    int fdcp2[2];
    if(pipe(fdcp1) < 0) {
        fprintf(stderr, "pipe unsuccessfull\n");
        return EXIT_FAILURE;
    }
    if(pipe(fdcp2) < 0) {
        fprintf(stderr, "pipe unsuccessfull\n");
        return EXIT_FAILURE;
    }

    pid_t chpid1 = fork();
    if(chpid1 < 0) {
        fprintf(stderr, "fork unsuccessfull\n");
        return EXIT_FAILURE;
    }
    else if(chpid1 == 0) {
        close(fdcp2[0]);
        close(fdcp2[1]);

        close(fdcp1[1]);
        dup2(fdcp1[0], STDIN_FILENO);
        execlp("./forksort", "child1", NULL);
    }else {
        close(fdcp1[0]);
        dup2(fdcp1[1], STDOUT_FILENO);

        double half = (nrrows / 2);
        int h = half;
        char b[2];
        b[0] = '0' + h;
        b[1] = '\n';
        write(fdcp1[1], b, sizeof(b));

        for(i = 0; i < h; i ++) {
            rows[i][strlen(rows[i])] = '\0';
            write(fdcp1[1], rows[i], sizeof(rows[i]));
        }

        pid_t chpid2 = fork();
        if(chpid2 < 0) {
            fprintf(stderr, "fork unsuccessfull\n");
            return EXIT_FAILURE;
        }else if(chpid2 == 0) {
            close(fdcp1[0]);
            close(fdcp1[1]);

            close(fdcp2[1]);
            dup2(fdcp2[0], STDIN_FILENO);
            execlp("./forksort", "child2", NULL);
        }else {
            close(fdcp2[0]);
            dup2(fdcp2[1], STDOUT_FILENO);
            half = (nrrows / 2);
            h = half;
            char b[2];
            b[0] = '0' + (nrrows - h);
            b[1] = '\n';
            write(fdcp2[1], b, sizeof(b));

            for(i = h; i < nrrows; i ++) {
                rows[i][strlen(rows[i])] = '\0';
                write(fdcp2[1], rows[i], sizeof(rows[i]));
            }
        }
    }
    return 0;
}
约翰·布林格

修改与开放流关联的文件描述符是不好的消息。我认为这很可能会给您带来麻烦,此外,这里不需要这样做。父级应该改用fdopen()在管道末端上打开新流,并通过子级而不是通过标准流对其子级进行I / O。除了更安全之外,还使流程的原始标准流可用于与其父流程进行通信。

使用这种方法,您甚至可以流传输要在进程之间来回排序的字符串,而不是在每个进程的内存中冗余地缓冲它们的块。例如,您可以执行以下操作:

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char * argv[]) {
    char * buffer = NULL;
    size_t buflen = 0;
    int nrrows;
    int fdpc1[2];
    int fdcp1[2];
    int fdpc2[2];
    int fdcp2[2];
    pid_t chpid1;
    pid_t chpid2;
    FILE *pipeout;
    FILE *pipein1;
    FILE *pipein2;
    int half;
    int i;

    fprintf(stderr, "%s!!!!!!!!!!!!!!!!!\n", argv[0]);

    getline(&buffer, &buflen, stdin);
    fprintf(stderr, "number: %s from %s\n", buffer, argv[0]);
    nrrows = strtol(buffer, NULL, 10);

    if(nrrows <= 0) {
        fprintf(stderr, "This is not a valid >0 number\n");
        return EXIT_FAILURE;
    } else if (nrrows == 1) {
        /* ... read and echo back the one row ... */
        getline(&buffer, &buflen, stdin);
        fprintf(stderr, "%s", buffer);
        return EXIT_SUCCESS;
    }

    /* There are at least two rows to sort */

    if (pipe(fdcp1) < 0) {
        fprintf(stderr, "pipe unsuccessfull\n");
        return EXIT_FAILURE;
    }
    if (pipe(fdpc1) < 0) {
        fprintf(stderr, "pipe unsuccessfull\n");
        return EXIT_FAILURE;
    }

    chpid1 = fork();
    if (chpid1 == 0) {
        /* this is child process 1 */
        close(fdcp1[1]);
        close(fdpc1[0]);
        dup2(fdcp1[0], STDIN_FILENO);
        close(fdcp1[0]);
        dup2(fdpc1[1], STDOUT_FILENO);
        close(fdpc1[1]);
        execlp("./forksort", "child1", NULL);
    } else if (chpid1 < 0) {
        fprintf(stderr, "fork unsuccessfull\n");
        return EXIT_FAILURE;
    }

    /* this is the parent process */

    close(fdcp1[0]);
    close(fdpc1[1]);

    if (pipe(fdcp2) < 0) {
        fprintf(stderr, "pipe unsuccessfull\n");
        return EXIT_FAILURE;
    }
    if (pipe(fdpc2) < 0) {
        fprintf(stderr, "pipe unsuccessfull\n");
        return EXIT_FAILURE;
    }

    chpid2 = fork();
    if (chpid2 == 0) {
        /* this is child process 2 */
        close(fdcp1[1]);
        close(fdpc1[0]);
        close(fdcp2[1]);
        close(fdpc2[0]);
        dup2(fdcp2[0], STDIN_FILENO);
        close(fdcp2[0]);
        dup2(fdpc2[1], STDOUT_FILENO);
        close(fdpc2[1]);
        execlp("./forksort", "child2", NULL);
    } else if (chpid2 < 0) {
        fprintf(stderr, "fork unsuccessfull\n");
        return EXIT_FAILURE;
    }

    /* this is the parent process */

    close(fdcp2[0]);
    close(fdpc2[1]);

    /* copy the first half of the lines from input to child 1 */

    pipeout = fdopen(fdcp1[1], "w");
    if (pipeout == NULL) {
        fprintf(stderr, "fdopen unsuccessful\n");
        return EXIT_FAILURE;
    }

    half = nrrows / 2;
    fprintf(pipeout, "%d\n", half);
    for (i = 0; i < half; i += 1) {
        getline(&buffer, &buflen, stdin);
        fprintf(stderr,"row[%d] from %s: %s", i, argv[0], buffer);
        fputs(buffer, pipeout);
    }
    fclose(pipeout);

    /* copy the second half of the lines from input to child 2 */

    pipeout = fdopen(fdcp2[1], "w");
    if (pipeout == NULL) {
        fprintf(stderr, "fdopen unsuccessful\n");
        return EXIT_FAILURE;
    }

    fprintf(pipeout, "%d\n", nrrows - half);
    for (; i < nrrows; i += 1) {
        getline(&buffer, &buflen, stdin);
        fprintf(stderr,"row[%d] from %s: %s", i, argv[0], buffer);
        fputs(buffer, pipeout);
    }
    fclose(pipeout);

    /* now read and merge sorted lines from the children */

    pipein1 = fdopen(fdpc1[0], "r");
    pipein2 = fdopen(fdpc2[0], "r");
    if (pipein1 == NULL || pipein2 == NULL) {
        fprintf(stderr, "fdopen unsuccessful\n");
        return EXIT_FAILURE;
    }

    /* ... */

    fclose(pipein1);
    fclose(pipein2);

    return 0;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C语言中父母与两个孩子之间的管道

来自分类Dev

如何使用管道从两个孩子向父母发送C语言中的数据?

来自分类Dev

在C语言中先于父母执行孩子

来自分类Dev

休眠两个父母一个孩子映射

来自分类Dev

从两个父母 CSS 获取所有特定的孩子

来自分类Dev

在c语言中,两个字符串之间的冒号是什么?

来自分类Dev

在c语言中,两个字符串之间的冒号是什么?

来自分类Dev

当孩子等待父母的设置状态完成时,如何在两个有状态小部件之间使用 FutureBuilder?

来自分类Dev

在C语言中,与malloc和变量数组声明有关的两个给定代码段之间有什么区别?

来自分类Dev

C语言中的多级管道

来自分类Dev

您如何从两个孩子都在C的管道中读取内容?

来自分类Dev

R语言中两个括号的含义是什么

来自分类Dev

两个块之间的管道算子

来自分类Dev

单击孩子时,孩子和父母会触发两个不同的事件

来自分类Dev

如何在两个父母之间转换div?

来自分类Dev

父母div有两个孩子。即使不显示其他孩子,也要始终让一个孩子填满父母吗?

来自分类Dev

父母div有两个孩子。即使不显示其他孩子,也总是让一个孩子填满父母吗?

来自分类Dev

从第n个孩子两个到父母的角度输出变量

来自分类Dev

比较两个不同文件中的每一行,并打印C语言中不同的行

来自分类Dev

两个不同父母的孩子可以在React中拥有相同的键吗

来自分类Dev

如何用两个孩子扩展相似的父母来创建地图?

来自分类Dev

C语言中的管道问题(Linux)

来自分类Dev

如何派生n个孩子并让他们在C语言中执行不同的任务?

来自分类Dev

管道同一个父母的多个孩子

来自分类Dev

从不是 jQuery 中祖父母的前两个孩子的父母中选择不是 h3 的孩子节点

来自分类Dev

如何在两个程序之间建立双向管道?

来自分类Dev

C语言中“ *”,“ *”和“ *”指针之间的区别

来自分类Dev

在C语言中使用scanf()连续读取两个字符

来自分类Dev

在C语言中使用“ fscanf”如何分割两个字符串?

Related 相关文章

  1. 1

    C语言中父母与两个孩子之间的管道

  2. 2

    如何使用管道从两个孩子向父母发送C语言中的数据?

  3. 3

    在C语言中先于父母执行孩子

  4. 4

    休眠两个父母一个孩子映射

  5. 5

    从两个父母 CSS 获取所有特定的孩子

  6. 6

    在c语言中,两个字符串之间的冒号是什么?

  7. 7

    在c语言中,两个字符串之间的冒号是什么?

  8. 8

    当孩子等待父母的设置状态完成时,如何在两个有状态小部件之间使用 FutureBuilder?

  9. 9

    在C语言中,与malloc和变量数组声明有关的两个给定代码段之间有什么区别?

  10. 10

    C语言中的多级管道

  11. 11

    您如何从两个孩子都在C的管道中读取内容?

  12. 12

    R语言中两个括号的含义是什么

  13. 13

    两个块之间的管道算子

  14. 14

    单击孩子时,孩子和父母会触发两个不同的事件

  15. 15

    如何在两个父母之间转换div?

  16. 16

    父母div有两个孩子。即使不显示其他孩子,也要始终让一个孩子填满父母吗?

  17. 17

    父母div有两个孩子。即使不显示其他孩子,也总是让一个孩子填满父母吗?

  18. 18

    从第n个孩子两个到父母的角度输出变量

  19. 19

    比较两个不同文件中的每一行,并打印C语言中不同的行

  20. 20

    两个不同父母的孩子可以在React中拥有相同的键吗

  21. 21

    如何用两个孩子扩展相似的父母来创建地图?

  22. 22

    C语言中的管道问题(Linux)

  23. 23

    如何派生n个孩子并让他们在C语言中执行不同的任务?

  24. 24

    管道同一个父母的多个孩子

  25. 25

    从不是 jQuery 中祖父母的前两个孩子的父母中选择不是 h3 的孩子节点

  26. 26

    如何在两个程序之间建立双向管道?

  27. 27

    C语言中“ *”,“ *”和“ *”指针之间的区别

  28. 28

    在C语言中使用scanf()连续读取两个字符

  29. 29

    在C语言中使用“ fscanf”如何分割两个字符串?

热门标签

归档