Linux 上的两个过滤器通过两个命名管道 (FIFO) 循环链接

发布于 2024-10-14 12:03:43 字数 1961 浏览 9 评论 0原文

我想让两个进程通过 Linux 上的两个命名管道相互通信。 每个进程都是一个 Unix 过滤器:它在其标准输入上读取数据并在其标准输出上写入数据。 它们是循环链接的,因为第一个的输出是第二个的输入,反之亦然。

这是第一个过滤器(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;
}

这是第二个过滤器(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 ac && gcc -o B bc),创建两个 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

为什么我没有得到我期望的结果?

提前致谢。

I want to make two processes communicate with each other via two named pipes on Linux.
Each process is a Unix filter : it reads data on its standard input and writes data on its standard output.
They are circularly linked in that the output of the first is the input of the second and the other way around.

Here is the code of the first filter (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;
}

Here is the code of the second filter (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;
}

I compile (gcc -o A a.c && gcc -o B b.c), create two fifos (mkfifo b2a ; mkfifo a2b), run the first program in a terminal (cat a2b | ./B > b2a), open a new terminal and run the second program (cat b2a | ./A > a2b).

What I expected was an infinite loop with A and B increasing the number in turn, but what I get is B stuck, not being able to read what A wrote.

In the term where I launched B, I get :

B is going to read

In the terminal where I launched A, I get :

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

If I use 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

Why do I not get what I expected ?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沫尐诺 2024-10-21 12:03:43

写入后需要显式fflush,以便输出通过管道。否则,输出可能会保留在写入进程的 stdio 缓冲区中。 (您还可以使用 setvbuf(stdio, NULL, _IONBF, 0) 关闭缓冲。)

You need to explicitly fflush after writing, so that the output goes through the pipe. Otherwise, the output may stay in the writing process' stdio buffers. (You can also turn off buffering with setvbuf(stdio, NULL, _IONBF, 0).)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文