2

fifo を使用して 2 つのプロセス間で情報をやり取りしようとしています。ある程度までは機能しますが、読み取りがブロックされます。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);

これは、読み取り機能がブロックされている場所です

上記の 2 つの 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

そしたらブロックされるだけ

4

1 に答える 1

2

簡潔で簡単な答えは、何らかの外部同期メカニズムなしで双方向通信に単一の fifo を使用すべきではないということです。

詳しく説明すると、Unix パイプ、または fifo は、配管タイプのパイプとして視覚化するのが最適ではありません。それは貯蔵タンクのようなもので、そこから出入りするパイプがあります。標準的な使用法は、あるプロセスが書き込むことでタンクを満たし、別のプロセスが読み取ることでタンクを空にすることです。あなたのプログラムでは、fifo に書き込まれるすべてのものが、誰かが来て先着順でそれを読み取るまで、タンクに置かれます。したがって、Process1 プログラムは から書き込んだ 16.44 値を読み取り、oprnd2に戻しますresult。これにより、タンクが空のままになるため、Process2 が読み取るものは何もありません。それは競合状態になります。これら 2 つのコマンドを数百回実行すると、希望どおりに動作することが数回あると思います。 

概念実証だけが必要な場合は、FIFOsleepの前に Process1 に a を追加しreadます。より良い解決策は、各方向に 1 つずつ、2 つの fifo を使用することです。または、プロセス 2 がプロセス 1 に、それ (プロセス 2) が演算子と両方のオペランドを読み取り、結果 (たとえば、シグナルまたはセマフォ) を書き込んだことを知らせる方法を考案することもできますが、それは価値があるよりもおそらく面倒なことになるでしょう。 .

scanf別の問題として、おもちゃ、デモンストレーション、または使い捨てのプロトタイプ タイプのプログラム以外での使用を強くお勧めします。ユーザーがちょうど をヒットした場合Enter、プログラムはそこに永遠に留まります。行を読んで(バッファオーバーフローに確実に対処して)、それを呼び出すことをお勧めしますsscanf

ああ、また、コードをインデントしてください。

于 2013-01-25T03:17:30.413 に答える