2013-01-25 40 views
2

我试图在使用fifo的两个进程之间来回发送信息。它工作到一个点,但然后一个阅读块。我怀疑Process2是错误的地方。读取中间值时双向fifo通信块

处理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()调用被阻止。为什么?

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

看起来您正试图在两个进程之间创建客户端 - 服务器关系。如果你是,而且这是一个严肃的项目(即不只是一个演示或玩具),我建议你考虑使用远程过程调用(RPC)。 – Scott

回答

2

短期和简单的答案是,你不应该使用一个单一的FIFO用于双向通信而无需外部同步n机制。

详细说明:Unix管道或fifo并不是最佳的可视化管道类型管道。 它更像是一个储罐,管道通向它。标准用法是一个过程写入,从而填充罐体,另一个过程读取,从而排空罐体。在你的计划中,所有写到前沿的东西都会放在坦克里,直到有人前来阅读,先到先得。所以你的Process1程序读取16.44的值,它从oprnd2写回到result。这使得容器变空,所以Process2没有任何内容可以读取。这归结于竞争条件。我怀疑,如果你几次运行这两个命令,他们会按照你想要的方式工作几次。

如果您只是想要验证概念,请在fifo前read之前向Process1添加sleep。更好的解决方案是使用两个fifos,每个方向一个。或者你可以为Process2设计一些方法让Process1知道它(Process2)已经读取了操作符和两个操作数,并且写出了结果 - 例如信号或信号量 - 但这可能比它的值得更麻烦。

另一方面,我强烈建议不要使用scanf以外的任何东西,除了玩具,演示或丢弃原型类型的程序。如果用户点击输入,程序将永远坐在那里。我建议读一行(确保解决缓冲区溢出),然后在其上调用sscanf

哦,还有,请缩进你的代码。

+0

非常感谢你,解决了问题 – Neeraj

+0

不使用'scanf'的另一个原因 - 你显然知道它将新行保留在输入缓冲区中。我希望你们明白,总的来说,它的内容与其所需要的一样多,并且其余部分未读。所以,如果你的用户感到困惑并且在输入“'+ - *'”时会回应“'Enter operator'”提示符,那么'scanf'将读取'+','getchar()'将读取' ',并且'*'将留在输入流中,它会破坏'scanf(“%f”,&oprnd1);'。 – Scott

+0

是的,这是真的,我将不得不照顾这一点。再次感谢此支持@Scott – Neeraj