我正在尝试使用fifo在两个进程之间来回发送信息。它可以工作到一个点,但随后是一个读取块。我怀疑Process2是bug的所在。
处理1:
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
main()
{
char oprtr;
int fd1,fd0;
float oprnd1,oprnd2,result;
mkfifo("fifo1",0777);
fd1=open("fifo1",O_RDWR);
printf("fd1:%d\n",fd1);
printf("Add(+)\n");
printf("subtract(-)\n");
printf("multiply(*)\n");
printf("division(/)\n");
printf("Enter operator\n");
scanf("%c",&oprtr);
getchar();
write(fd1,&oprtr,sizeof(oprtr));
printf("Enter oprnd1\n");
scanf("%f",&oprnd1);
getchar();
write(fd1,&oprnd1,sizeof(oprnd1));
fd0=dup(fd1);
printf("Enter oprnd2\n");
scanf("%f",&oprnd2);
getchar();
if(write(fd0,&oprnd2,sizeof(oprnd2))==0)
perror("write : oprnd2:");
else
printf("writing oprnd2 done\n");
read(fd1,&result,sizeof(result));
printf("Result:%f\n",result);
}
过程2:
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
main()
{
int fd2,fd3;
char oprtr;
float oprnd1,oprnd2,result;
fd2=open("fifo1",O_RDWR);
printf("fd2:%d\n",fd2);
read(fd2,&oprtr,sizeof(oprtr));
printf("oprtr:%c\n",oprtr);
read(fd2,&oprnd1,sizeof(oprnd1));
printf("oprnd1:%f\n",oprnd1);
fd3=dup(fd2);
这是读取功能被阻止的地方
以上两个read()调用似乎工作正常,但以下read()调用被阻止。为什么呢?
if(read(fd3,&oprnd2,sizeof(oprnd2))==0) ////This is the problem
perror("read : oprnd2:");
else
printf("oprnd2:%f\n",oprnd2);
switch(oprtr)
{
case '+':result=oprnd1+oprnd2;
write(fd2,&result,sizeof(result));break;
case '-':result=oprnd1-oprnd2;
write(fd2,&result,sizeof(result));break;
case '*':result=oprnd1*oprnd2;
write(fd2,&result,sizeof(result));break;
case '/':result=oprnd1/oprnd2;
write(fd2,&result,sizeof(result));break;
default: printf("Wrong Choice\n");break;
}
}
1号航站楼:
Add(+)
subtract(-)
multiply(*)
division(/)
Enter operator
+
Enter oprnd1
14.56
Enter oprnd2
16.44
writing oprnd2 done
Result:16.440089
2号航站楼:
fd2:3
oprtr:+
oprnd1:14.560000
然后它就会被阻止
答案 0 :(得分:2)
简短而简单的答案是,如果没有一些外部同步机制,就不应该使用单个fifo进行双向通信。
详细说明:Unix管道或者fifo最好不能被视为管道型管道。
它更像是一个储水箱,管道通往它。标准用法是一个过程写入,从而填充油箱,另一个过程读取,从而排空油箱。在你的程序中,写入fifo的所有内容都会放在坦克中,直到有人出现并读取它,先来先到先得。因此,您的Process1程序将从oprnd2
写入的16.44值读回result
。这使得储罐空了,因此Process2没有任何东西可供阅读。归结为竞争条件。我怀疑,如果你将这两个命令运行几百次,它们就会按你想要的方式运行几次。
如果您只是想要概念验证,请在fifo的sleep
之前向Process1添加read
。一个更好的解决方案是使用两个fifos,每个方向一个。或者您可以为Process2设计一些方法让Process1知道它(Process2)已经读取了运算符和两个操作数并且已经写了结果 - 例如,信号或信号量 - 但这可能比它的价值更麻烦
另一方面,我强烈建议不要在玩具,演示或丢弃原型类型的程序中使用scanf
。如果用户点击 Enter ,程序将永远坐在那里。我建议读一行(确保解决缓冲区溢出),然后在其上调用sscanf
。
哦,还请你缩进你的代码。