我正在尝试使用fifo在两个进程之间来回发送信息。它可以工作到一定程度,但随后会阻止读取。我怀疑Process2是错误所在。

流程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

然后它被阻止

最佳答案

简短而简单的答案是,在没有某种外部同步机制的情况下,您不应使用单一的fifo进行双向通信。

详细说明:Unix管道或fifo最好不可视为管道类型的管道。
它更像是一个储 jar ,有进出的管道。标准用法是写入一个进程,从而填充容器,读取另一个进程,从而清空容器。在您的程序中,写入fifo的所有内容都放在槽中,直到有人过来阅读为止,先到先得。因此,您的Process1程序将从oprnd2写入的16.44值读回result。这将使容器空着,因此Process2无需读取任何内容。它归结为竞赛条件。我怀疑,如果您将这两个命令运行了数百次,它们会按您希望的方式运行几次。

如果只需要概念验证,请在来自fifo的sleep之前将read添加到Process1。更好的解决方案是使用两个fifo,每个方向一个。或者,您可以为Process2设计某种方式,让Process1知道它(Process2)已经读取了该运算符和两个操作数,并写入了结果(例如,信号或信号量),但是这可能比它值得的麻烦更多。 。

在另一个问题上,我强烈建议您不要在玩具,演示程序或一次性原型(prototype)程序以外的任何类型中使用scanf。如果用户仅按Enter键,则该程序将永远停在那里。我建议阅读一行(确保解决缓冲区溢出问题),然后在其上调用sscanf

哦,而且,请缩进您的代码。

关于c - 读取中间值时双向fifo通信块,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14517252/

10-14 17:05