gpt4 book ai didi

c - 超过 2 个子节点之间的管道失败 - C

转载 作者:行者123 更新时间:2023-11-30 15:07:46 24 4
gpt4 key购买 nike

如何在 3 个或更多 child 之间制作功能性管道?

我使用这个命令:

./function n ,其中 n 是子代的数量。

父亲制造了 n 个管道和 n 个 child 。

之后, children 关闭他们不会使用的管道。

然后父亲在第一个管道中写入一些内容,第一个 child 读取它,并将其写入下一个管道。最后一个 child 应该将内容写入stdout

当我只使用 1 个 child 时,效果非常好。当我尝试使用 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);
}

编辑:我发布了对我有用的代码

最佳答案

您有几个问题。

  • int* pp[2] 并不意味着您认为的意思。这是一个由两个指向 int 的指针组成的数组,但您似乎想要的是一个指向由两个 int 组成的数组的指针。那将是int (*pp)[2]。您的段错误可能与此有关。

  • 更正了 pp 的类型后,接下来必须正确分配它;具体来说,全部集中在一个 block 中。这是实现这一目标的最简洁的方法(请注意,不涉及循环,并且所需的大小是根据指针目标的大小定义的):

    pp = malloc(childrens * sizeof(*pp));

如果您希望父级提前创建所有管道,那么您确实需要使用循环。

  • 父级应该每次关闭未使用的管端一次,但是每个子级 fork 时都将其关闭一次。将其移出循环。

  • 虽然 C 允许这样做,但允许控制到达 main() 的右括号是很糟糕的形式。请使用 return 语句或调用 exit()

  • 您假设 I/O 不会拆分数据,因此单个 write()read() 调用就足够了。这可能对您有用,但实际上并不可靠。您应该在必要时循环 write()read() 通过多次调用来传输全部字节数。使用这些函数的返回值可以帮助解决此问题。

  • 前面的内容意味着您需要在进程之间进行通信,以读取任何一条消息中的字节数。您可以使用终止符(例如换行符或空字节)来做到这一点,或者首先发送一个(固定大小)整数来说明同一消息中后面有多少个字符。

关于c - 超过 2 个子节点之间的管道失败 - C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37974261/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com