1

Linuxで2つの名前付きパイプを介して2つのプロセスを相互に通信させたいと思います。各プロセスはUnixフィルターです。標準入力でデータを読み取り、標準出力でデータを書き込みます。これらは、最初の出力が2番目の入力であり、その逆であるという点で循環的にリンクされています。

これが最初のフィルター(ac)のコードです:

#include <stdio.h>

int main( void  ){
  FILE* ferr = fopen( "/dev/stderr", "w" );
  double d;

  fprintf(ferr,"A is going to write\n");
  printf("%lf\n",1.);
  fprintf(ferr,"A wrote %lf\n",1.);

  while( 1 ){
    fprintf(ferr,"A is going to read\n");
    if( scanf("%lf",&d) == EOF ){
      break;
    }
    fprintf(ferr,"A recieved : %lf\n",d);
    d += 1;
    fprintf(ferr,"A is going to write\n");
    printf("%lf\n",d);
    fprintf(ferr,"A wrote %lf\n",d);
  }
  return 0;
}

2番目のフィルター(bc)のコードは次のとおりです。

#include <stdio.h>

int main( void  ){
  FILE* ferr = fopen( "/dev/stderr", "w" );
  double d;

  while( 1 ){
    fprintf(ferr,"B is going to read\n");
    if( scanf("%lf",&d) == EOF ){
      break;
    }
    fprintf(ferr,"B recieved : %lf\n",d);
    d += 1;
    fprintf(ferr,"B is going to write\n");
    printf("%lf\n",d);
    fprintf(ferr,"B wrote %lf\n",d);
  }
  return 0;
}

コンパイル(gcc -o A a.c && gcc -o B b.c)、2つのFIFO()を作成mkfifo b2a ; mkfifo a2bし、ターミナルで最初のプログラムを実行し(cat a2b | ./B > b2a)、新しいターミナルを開き、2番目のプログラムを実行します(cat b2a | ./A > a2b)。

私が期待したのは、AとBが順番に数を増やす無限ループでしたが、私が得たのはBがスタックし、Aが書いたものを読み取ることができないことです。

私がBを立ち上げた期間では、次のようになります。

B is going to read

Aを起動したターミナルでは、次のようになります。

A is going to write
A wrote 1.000000
A is going to read

lsofを使用する場合:

lsof b2a a2b
COMMAND   PID      USER   FD   TYPE DEVICE SIZE/OFF      NODE NAME
cat     24382 john doe    3r  FIFO   0,22      0t0 282149936 a2b
B       24383 john doe    1w  FIFO   0,22      0t0 282149934 b2a
cat     24413 john doe    3r  FIFO   0,22      0t0 282149934 b2a
A       24414 john doe    1w  FIFO   0,22      0t0 282149936 a2b

期待したものが得られないのはなぜですか?

前もって感謝します。

4

1 に答える 1

6

fflush出力がパイプを通過するように、書き込み後に明示的に行う必要があります。そうしないと、出力が書き込みプロセスのstdioバッファに留まる可能性があります。(でバッファリングをオフにすることもできますsetvbuf(stdio, NULL, _IONBF, 0)。)

于 2011-01-25T14:52:46.280 に答える