Perl中的并发输入输出

5

最近我开始学习管道,觉得很有趣。虽然在某些部分卡住了,但我认为大部分都已经弄清楚了,但是我无法弄明白如何同时将输入转发到程序并从该程序输出。

目前我有一个处理管道的Perl脚本:

#!/usr/bin/perl
use strict;
use warnings;
use threads;
use FileHandle;
use IPC::Open2;

my $cv_program = "./test"; #test is the compiled C program below
my $cv_message = "";
my $cv_currentkey = "";
my $pid = open2(*PIN, *POUT, $cv_program);
my $thread_pipeout = threads->create('PIPEOUT', \&PIN);

$thread_pipeout->detach();

while($cv_currentkey ne "\n")
{
    $cv_currentkey = getc(STDIN);
    $cv_message .= $cv_currentkey;
}
print POUT $cv_message;

sub PIPEOUT
{
    my $PIN = shift;
    while(<PIN>)
    {
        print $_;
    }
}

接下来我有一个C程序,它只输出一些内容,然后要求输入一个字符串,最后打印出该字符串:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char input[100] = {0};

    printf("This is a test.\n");
    fgets(input, 100, stdin);
    printf("You entered %s\n", input);
    return 0;
}

运行Perl脚本后的输出为:
~/Programming/Perl Pipes$ ./pipe.pl
Hello
This is a test.
You entered Hello

注意它在接收输入时会阻塞,然后一次性打印所有内容。我需要它先打印“This is a test”,然后像实际程序一样等待输入。

另外,我想指出的是我在Perl脚本中使用getc而不是STDIN是因为我找不到方法让STDIN不会阻塞来自test.c的输出,但目前getc的效果也不太好。

1个回答

7
我认为问题主要在C端,而不是Perl端。C看到它的标准输出将被送到管道中,因此它并不非常在意在查询标准输入之前刷新其标准输出缓冲区。
为了解决这个问题,您只需要添加这一行即可:
fflush(stdout);

在第一个printffgets之间。(免责声明:未经过测试。)

这个答案非常简单而且有效。不过在两个printf语句后面我必须加上fflush。如果我在最后一个printf语句后面不加,那么消息就永远不会被打印出来。感谢您的快速回答。 - ozdrgnaDiies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接