Два фильтра, циклически связанные двумя именованными каналами (FIFO) в Linux.

Я хочу, чтобы два процесса взаимодействовали друг с другом через два именованных канала в Linux. Каждый процесс представляет собой фильтр Unix: он считывает данные со своего стандартного ввода и записывает данные со своего стандартного вывода. Они циклически связаны в том смысле, что выход первого является входом второго и наоборот.

Вот код первого фильтра (a.c):

#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;
}

Вот код второго фильтра (b.c):

#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), создаю два файла fifo (mkfifo b2a ; mkfifo a2b), запускаю первую программу в терминале (cat a2b | ./B > b2a), открываю новый терминал и запускаю вторую программу (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

Почему я не получаю того, что ожидал?

Заранее спасибо.


person user589082    schedule 25.01.2011    source источник


Ответы (1)


Вам нужно явно fflush после записи, чтобы вывод шел по каналу. В противном случае вывод может остаться в stdio буферах процесса записи. (Вы также можете отключить буферизацию с помощью setvbuf(stdio, NULL, _IONBF, 0).)

person Fred Foo    schedule 25.01.2011
comment
Спасибо. Я добавил fflush(NULL); после каждого printf и теперь это работает. - person user589082; 25.01.2011