Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 与单亲进程通信的多个子进程_C_Linux_Unix_Pipe_Posix - Fatal编程技术网

C 与单亲进程通信的多个子进程

C 与单亲进程通信的多个子进程,c,linux,unix,pipe,posix,C,Linux,Unix,Pipe,Posix,我需要尝试创建一个单亲进程,并与多个子进程进行有意义的通信。这意味着发送数据并让他们将数据发送回单亲家长。首先,我试着让我的孩子们输出一些东西,让我的父母捕捉到,最终目标是让所有孩子与父母进行双向沟通。为了实现这一点,我为每个子级实例化了两个管道,并将所有管道存储到名为pipes的多维数组中。多维管道数组的存储方式是,每个索引i用于ith+1子级,[i][0]索引具有一个管道,该管道专门用于父级与子级对话,而[i][1]索引有一个管道,专门供子项与父项通话。子进程都是非常简单的子进程,只执行这段

我需要尝试创建一个单亲进程,并与多个子进程进行有意义的通信。这意味着发送数据并让他们将数据发送回单亲家长。首先,我试着让我的孩子们输出一些东西,让我的父母捕捉到,最终目标是让所有孩子与父母进行双向沟通。为了实现这一点,我为每个子级实例化了两个管道,并将所有管道存储到名为
pipes
的多维数组中。多维管道数组的存储方式是,每个索引
i
用于
ith+1
子级,
[i][0]
索引具有一个管道,该管道专门用于
父级
子级
对话,而
[i][1]
索引有一个管道,专门供
子项
父项
通话。
子进程
都是非常简单的子进程,只执行这段代码:

富科
然而,我的代码似乎总是卡在
块中,而底部的
块用于从管道中读取,因为当我删除它时,代码会完全执行。我有一些猜测,可能我们有僵尸的孩子(因为他们在父母到达for循环之前终止)。我不确定孩子死后管道会发生什么情况(除了与之相关的文件描述符被关闭),我们仍然可以从中读取(我对此也很好奇)。然而,根据我过去的经验,你似乎仍然可以。我已经在这个问题上纠缠了好几个小时,任何见解都将受到极大的赞赏(或者我可能做错了什么)

当您
读取
4096
字节时,某些系统(如linux)将尝试满足完整请求,并将阻塞,直到另一端1)写入所有
4096
字节或2)关闭写入端。 写入端的所有副本都需要关闭,而不仅仅是一个副本。
dup
ing创建对文件描述符的新引用。当您使用
fork
时,就好像您复制了当时打开的所有文件描述符。 要完成
读取
,您需要满足完整的4096字节请求,或者生成一个EOF,如果要生成EOF,则需要关闭写入端的所有克隆

因为您的每个子级执行,所以您可以设置每个管道
O_CLOEXEC
(使用
fcntl
),并在分叉将要写入写入端的子级后关闭父级中的每个写入端


(除此之外,请确保包含所有需要的标题,并确保处理所有错误)。

在这种情况下,使用套接字实际上可能更简单。至少要考虑的文件描述符要少得多。可能需要更多的代码来设置,但一旦设置完成,就和读取/写入管道一样简单。@JoachimPileborg,谢谢你的建议,但我想了解更多关于管道的信息,并想尝试使用管道来实现这一点。关于你的代码,你确定“字符串”您试图在进程之间传输的是C样式的字符串,即以零结尾?否则,您将有未定义的行为试图在父进程中打印它们。您需要在调用
execl
之前关闭所有管道。在最后一个
for
循环之前关闭所有写入管道。您必须小心通过,管道是数据流,没有任何特定的数据包边界。虽然对管道的写入将是原子的(因为所有数据都被推送到管道,或者写入调用将失败),但管道中的实际数据流中没有边界,这意味着一个
read
调用可能不会实际读取管道中当前的所有数据,并且您可能必须使用循环来获取所有数据。这里的问题是,如果您读取了发送的一些文本,但没有读取包含字符串终止符的部分。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv) {
    printf("Hi there!");
    close(STDOUT_FILENO); //Close our write end
    close(STDIN_FILENO); //Close our read end
    //Else do nothing
    return 0;
}
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <math.h>
#define MAXSIZE 4096
#define CHILDREN 5

int main(int argc, char ** argv) {
    //Needs command line arguments
    int ** pipes[CHILDREN]; //The multi-dimensional array that contains CHILDREN pipes
    //Allocate the space
    for (int i = 0; i < CHILDREN; i++) {
        //Each children will need two pipes, one for comunicating and one for writing
        pipes[i] = malloc(sizeof(int*) * 2);
        pipes[i][0] = malloc(sizeof(int) * 2); //This pipe is specifically parent to child
        pipes[i][1] = malloc(sizeof(int) * 2); //This pipe is for specifically for the child to parent

        //Create the pipes
        if (pipe(pipes[i][0]) == -1 || pipe(pipes[i][1]) == -1) {
            //There was a failure in generating one of the pipes
            perror("Error on generating the pipe");
        }
    }
    //Spawn the child processses
    for (int i = 0; i < CHILDREN; i++) {
        int status = fork(); //Fork a child
        switch (status) {
            case -1:
                perror("Failed to fork the process");
                exit(1);
                break;
            case 0:
                //Child process, exec the floor
                dup2(pipes[i][0][0], fileno(stdin));
                dup2(pipes[i][1][1], fileno(stdout));
                execl("./foo", "");
                break;
        }
        //Parent continues the loop to spawn more children
    }
    
    char readed[MAXSIZE] = ""; //Reading buffer
    //Now read back from the pipes
    for (int i = 0; i < CHILDREN; i++) {
        while (read(pipes[i][1][0], readed, MAXSIZE) > 0) {
            printf("From pipe %d, we have read %s\n", i, readed);
        }
    }
    return 1;
}