我正在尝试将几个perl程序连接在一起,而且从我读过的所有内容来看,管道程序应该全部打开并且并行运行。无论我做了什么,情况似乎并非如此。这是简化版本:
./视频
#!/usr/bin/env perl
my $i = 0;
while($i<10){
my $time = localtime(time);
print "VID: $time $i\n";
sleep 1;
$i++;
}
./控制器
#!/usr/bin/env perl
while(my $line = <STDIN>){
my $time = localtime(time);
print "CTRL: $time $line";
}
./管道
#!/usr/bin/env perl
open(my $controller, "|./controller") || die "Can't fork: $!";
open(STDOUT, ">&", $controller);
open(my $video, "|./video") || die "Can't fork: $!";
print STDERR "All processes started\n";
我尝试了两种方式执行它,但两者都产生了相同的输出:
<16:34:21> rswhiting@Minas-Tirith:~/code/Pipes $ ./pipes
All processes started
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:22 2014 0
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:23 2014 1
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:24 2014 2
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:25 2014 3
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:26 2014 4
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:27 2014 5
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:28 2014 6
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:29 2014 7
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:30 2014 8
CTRL: Sun Apr 20 16:34:32 2014 VID: Sun Apr 20 16:34:31 2014 9
<16:34:49> rob@Minas-Tirith:~/code/Pipes $ ./video | ./controller
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:15 2014 0
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:16 2014 1
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:17 2014 2
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:18 2014 3
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:19 2014 4
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:20 2014 5
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:21 2014 6
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:22 2014 7
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:23 2014 8
CTRL: Sun Apr 20 16:35:25 2014 VID: Sun Apr 20 16:35:24 2014 9
<16:35:25> rob@Minas-Tirith:~/code/Pipes $
视频节目的时间戳应按原样递增,但控制程序接收它们的时间相同(视频节目结束后)。如何使控制器在生成数据时接收数据而不是事后?
答案 0 :(得分:4)
这是因为video
程序中的STDOUT缓冲。 print
仅在进入交互式终端时才进行行缓冲。否则它使用更大的缓冲区,当video
退出时,累积的输出将在一个大块中发出。每次打印后尝试冲洗或使用autoflush。
$| = 1; # Enables autoflush
顺便说一下,我不明白为什么你打开一个管道video
,它什么都没读。它应该是
system "./video";
如果您的程序无法修改但无法自动刷新,则表示您遇到了麻烦。除此之外,你不是。您可以使用伪终端而不是管道。我从来没有这样做过。但是,“UXIX编程接口”一书的第64章是关于伪终端的。