我正在学习使用叉子和管道。我写了下面的代码.child1写了#34;孩子1"和child2写" child 2",父母读取值。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
int pfds[2];
char buf[30];
pipe(pfds);
if(fork() == 0) //child 1
{
close(pfds[0]);
write(pfds[1],"child 1",sizeof(buf));
}
else
{
if(fork() == 0) //child2
{ close(pfds[0]);
write(pfds[1],"child 2",sizeof(buf));
}
else
{
close(pfds[1]);
read(pfds[0],buf,sizeof(buf));
printf(" read: %s ",buf);
wait(NULL);
}
close(pfds[1]);
read(pfds[0],buf,sizeof(buf));
printf(" read: %s ",buf);
wait(NULL);
}
}
我的输出是:read:some_garbage_value read:child 1 read:child 2
为什么我读了3次?我只想要它2次(child1和child2)。如何执行语句?
P.S:抱歉,如果这是一个菜鸟问题。我刚刚开始学习fork(),exec()和管道。
答案 0 :(得分:1)
忽略代码中过多的错误和缺少检查(已经在注释中指出),您要求的问题是由fork()
将流分成两个在两个执行的路径的事实给出的不同的过程。这意味着在fork()
之后,您将有两个并行执行,其中一个fork()
返回0而另一个返回创建进程的pid。
因此,在第一个fork()
之后,您将有一个执行if
分支的进程和一个执行else
分支的进程。
然后你再次以这种方式完成一段代码:
if (fork() == 0) {
code1;
}
else {
code2;
}
code3;
现在想象一下fork()返回不同值的两个不同进程,你有:
if (0 == 0)
code1;
else
code2;
code3;
和
if (123 == 0)
code1;
else
code2;
code3;
这意味着两条路径被解析为:
code1;
code3;
和
code2;
code3;
这解释了为什么您创建的第二个孩子尝试阅读。
答案 1 :(得分:1)
以下是发生的事情:
First fork:
pfds[0]
,写道......然后在其他人之后继续阅读刚刚关闭的pfds[0]
。由于您没有测试read
的返回值,第二个子项会将随机缓冲区打印到stdout pfds[0]
读取缓冲区并将其打印到stdout,然后在if之后继续读取第二个缓冲区并将其打印到stdout 所以我们有一个垃圾输出和两个正确的输出。编译器是对的。
您可以通过立即从孩子2返回来轻松修复它:
if(fork() == 0) //child2
{ close(pfds[0]);
write(pfds[1],"child 2",sizeof(buf));
return 0; /* stop child2 immediately */
}
else