Linux 上的两个过滤器通过两个命名管道 (FIFO) 循环链接
我想让两个进程通过 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
写入后需要显式
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 withsetvbuf(stdio, NULL, _IONBF, 0)
.)