【发布时间】:2018-12-16 23:52:46
【问题描述】:
我现在正在学习如何正确使用管道。我找到了仅用于在父级中写入和在子级中读取的示例,但我想知道如何反向操作。我试过这样:
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
int main(){
int p1[2], p2[2];
char original[]="This is a string\n ";
pid_t child2;
pid_t child=fork();
if (child>0)
{
child2 = fork();
if(child2>0){
wait();
printf("I'm the parrent.\n");
close(p1[1]);
close(p2[1]);
printf("Parrent read p1:\n");
if (read(p1[0], original, sizeof(original)) == -1)
perror("read() error in parent p1");
else printf("parent read '%s' from pipe 1\n", original);
printf("Parrent read p2:\n");
if (read(p2[0], original, sizeof(original)) == -1)
perror("read() error in parent p2");
else printf("parent read '%s' from pipe 2\n", original);
}
else{
printf("Child2 \n");
pipe(p2);
close(p2[0]);
if (write(p2[1], original, sizeof(original)+1) == -1)
perror("write() error in child2");
//close(p2[1]);
}
}
else
{
printf("Child1 \n");
pipe(p1);
close(p1[0]);
if (write(p1[1], original, sizeof(original)+1) == -1)
perror("write() error in child1");
//close(p1[1]);
}
return 0;
}
但是这种方式让我在阅读父母时出错。 read() error in parent p1: Bad file descriptor 两次,p1 和 p2。那么,我可以这样做吗?或者这只是一些微不足道的错误?
【问题讨论】:
-
完全可以做到;你只是颠倒了正常的感觉。查找任何有关父子之间双向通信(不使用套接字)的问题,您会找到示例。您需要在 fork 将使用它的孩子之前创建管道。您还需要确保在每个子项和父项中关闭足够多的文件描述符。
-
您遇到错误是因为您没有在分叉之前调用 pipe() 并且您的 p1 和 p2 数组在大多数地方都未初始化。
-
也不清楚是否应该尽早等待。通常,您不应该调用
wait(),直到您在关闭管道之前在管道上获得EOF,然后等待死孩子(或即将成为死孩子)。您对wait()的调用是错误的,部分原因是您省略了#include <sys/wait.h>。你也缺少#include <unistd.h>,但你并不真正需要#include <sys/types.h>。 -
@Shawn 你说得对。请把它写成答案,然后我可以接受。谢谢!
-
如果包含标头,编译器应该告诉您
wait()需要一个您未提供的int *参数。您也可以提供一个空指针。您没有参数的调用是错误的,如果您包含<sys/wait.h>标头,编译器应该会抱怨(如果您不包含它,应该抱怨该函数未声明)。如果您没有收到投诉,则说明您的编译器太旧,或者您没有使用足够的警告选项(尽管警告选项不是必需的)。
标签: c pipe parent-child