我需要尝试有一个单亲繁殖和有意义的沟通与多个子进程。这意味着发送数据并让他们将数据发送回单亲。首先,我试着让我的孩子输出一些东西,让我的父母抓住它,最终目标是允许所有孩子与父母之间的双向交流。为了实现这一点,我为每个孩子实例化了两个管道,并将所有管道存储到一个称为pipes
的多维数组中。多维管道数组存储这样,每个索引i
都是为ith + 1
子索引,[i][0]
索引都有一个管道专门用于parent
与child
对话,[i][1]
索引有一个管道专门用于child
与parent
对话。children
进程都是非常简单的派生,只需执行这段代码:
食品
#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;
}
我的主代码就在这里,它首先创建所有必要的管道(每个孩子两个管道)。然后,我将
dup2
和STDIN
打印到我想要的管道上。fork_complex.c公司
#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;
}
然而,我的代码似乎总是被卡在底部的
STDOUT
块中以便从管道中读取,当我删除它时,代码将完全执行。我有一些猜测,可能我们有僵尸的孩子(因为他们在父母到达for循环之前终止)。我不确定孩子死后管道会发生什么情况(其他与之相关的文件描述符关闭),我们仍然可以从中读取(我对此也很好奇)。不过,根据我过去的经验,看来你还是可以的。我已经被这个问题困扰了好几个小时,任何洞察都会非常感激(或者我可能做错了什么)! 最佳答案
当您read
4096
字节时,某些系统(如linux)将尝试满足完整请求,并将阻塞,直到另一端1)写入所有4096
字节或2)关闭写入端。
写端的所有副本都需要关闭,而且不止一个。dup
ing创建对文件描述符的新引用。当您fork
时,就好像您dup
编辑了当时打开的所有文件描述符。
要完成read
,您要么需要满足完整的4096字节请求,要么生成一个EOF;要实现后者,需要关闭写端的所有克隆。
因为您的每个子级都是execs,所以您可以设置每个管道O_CLOEXEC
(使用fcntl
)和close
父级中的每个写端(在分叉要写入到写端的子级之后)。
(除此之外,请确保包含所需的所有标题,并确保处理所有错误)。
关于c - 许多子进程与单亲进行通信,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36118737/