如何在3个或更多孩子之间制作功能性管道?
我使用这个命令:
./function n
n
子女数量。
父亲制造了n
个管子和n
个孩子。
之后,孩子们关闭了他们不会使用的管道。
然后父亲在第一个管道中写入内容,第一个孩子读取它,并将其写入下一个管道。最后一个孩子应该在stdout
。
当我只使用一个孩子时,它完美无缺。当我尝试使用2个孩子时,最后一个从管道中读取:-1个字符,当我尝试使用3个孩子时,我发现了段违规,代码无效。
希望你能帮助我,这是代码。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
void use_pipes(int i);
void write_father(void);
int (*pp)[2];
int childrens;
int main(int argc, char* argv[]) {
childrens = atoi(argv[1]);
int p, i, j, aux;
printf("I'm the parent and i'm making %d childrens\n", childrens);
pp = malloc(sizeof (*pp) * childrens);
for (i = 0; i < childrens; i++) {
if (pipe(pp[i]) < 0) {
perror("Error in pipe()");
exit(1);
}
}//for
for (i = 0; i < childrens; i++) {
printf("I'm the parent pid: %d and I'm going to make the child nº: %d\n", getpid(), i);
p = fork();
switch (p) {
case -1:
printf("We couldn't make the child nº:%d\n", i);
exit(1);
case 0:
//printf("I'm nº: %d, and I start my code\n",i);
for (aux = 0; aux < childrens; aux++) {
if (aux == i) {
//printf("I'm the children nº: %d and I'm going to close the pipe[%d] of writing\n", i,i);
close(pp[i][1]);
} else if (aux == i + 1) {
//printf("I'm the children nº: %d and I'm going to close the pipe[%d] of reading\n", i,aux);
close(pp[aux][0]);
} else {
//printf("I'm the children nº: %d and I'm going to close the pipe[%d]\n", i,aux);
close(pp[aux][0]);
close(pp[aux][1]);
}
}//for
//printf("I finished to close my unused pipes\n");
use_pipes(i);
exit(0);
default:
break;
}//switch
}//for of fork
close(pp[0][0]);
for (j = 1; j < childrens; j++) {
close(pp[j][0]);
close(pp[j][1]);
}//for
write_father();
int status;
for (i = 0; i < childrens; i++) {
wait(&status);
}
}//main
void write_father() {
int wroten;
char buffer[50] = "Hello World";
int len = strlen(buffer);
wroten = write(pp[0][1], buffer, len);
printf("The parent wrote: %d characters\n", wroten);
}
void use_pipes(int n_children) {
int readed;
char buffer [50];
readed = read(pp[n_children][0], buffer, sizeof (buffer));
printf("Children %d readed from pipe[%d][0]: %d characters\n", n_children, n_children, readed);
if (n_children != childrens - 1) {
printf("Children %d write in the pipe[%d][1]: %d characters\n", n_children, n_children + 1, readed);
write(pp[n_children + 1][1], buffer, readed);
} else
write(1, buffer, readed);
}
编辑:我发布了适用于我的代码
答案 0 :(得分:1)
你有几个问题。
int* pp[2]
并不代表您认为的含义。这是一个指向int
的两个指针的数组,但您看起来想要的是一个指向两个int
数组的指针。那将是int (*pp)[2]
。您的分段错误可能与此有关。
更正了pp
的类型,接下来必须正确分配;特别是,所有在一个块。这是实现这一目标的最简洁方法(请注意,不涉及循环,并且所需大小是根据指针的目标大小定义的):
pp = malloc(childrens * sizeof(*pp));
如果您希望父级提前创建所有管道,那么您需要使用循环。
父母应该每次关闭未使用的管道末端,但是每个孩子分叉时它会关闭它们一次。将其移出循环。
虽然C允许,但允许控件到达main()
的右括号是不好的形式。请使用return
语句或致电exit()
。
您认为您的I / O不会拆分数据,因此单write()
和read()
次呼叫就足够了。这可能对你有用,但实际上并不可靠。您应该循环write()
和read()
以在必要时通过多次调用传输完整的字节数。使用这些函数的返回值来帮助解决这个问题。
前面提到您需要在进程之间进行通信,在任何一条消息中要读取多少字节。您可以使用终止符(例如换行符或空字节)执行此操作,或者首先发送一个(固定大小)整数,该整数表示同一消息中包含多少个字符。