bash管道中的第一个程序是阻塞的

时间:2014-04-20 22:52:38

标签: perl bash pipe fork

我正在尝试将几个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 $ 

视频节目的时间戳应按原样递增,但控制程序接收它们的时间相同(视频节目结束后)。如何使控制器在生成数据时接收数据而不是事后?

1 个答案:

答案 0 :(得分:4)

这是因为video程序中的STDOUT缓冲。 print仅在进入交互式终端时才进行行缓冲。否则它使用更大的缓冲区,当video退出时,累积的输出将在一个大块中发出。每次打印后尝试冲洗或使用autoflush。

$| = 1;  # Enables autoflush

顺便说一下,我不明白为什么你打开一个管道video,它什么都没读。它应该是

system "./video";

如果您的程序无法修改但无法自动刷新,则表示您遇到了麻烦。除此之外,你不是。您可以使用伪终端而不是管道。我从来没有这样做过。但是,“UXIX编程接口”一书的第64章是关于伪终端的。