无缓冲或行缓冲的 Perl STDIN

标签 perl io stdin buffering

我有一个 Perl 脚本,它接收从另一个程序通过管道传输的输入。它使用 8k(Ubuntu 默认)输入缓冲区进行缓冲,这会导致问题。我想使用行缓冲或完全禁用缓冲。看起来没有什么好方法可以做到这一点。有什么建议?

use IO::Handle;
use IO::Poll qw[ POLLIN POLLHUP POLLERR ];
use Text::CSV;

my $stdin = new IO::Handle;
$stdin->fdopen(fileno(STDIN), 'r');
$stdin->setbuf(undef);

my $poll = IO::Poll->new() or die "cannot create IO::Poll object";
$poll->mask($stdin => POLLIN);

STDIN->blocking(0);

my $halt = 0;
for(;;) {
    $poll->poll($config{poll_timout}); 

    for my $handle ($poll->handles(POLLIN | POLLHUP | POLLERR)) {
        next unless($handle eq $stdin);

        if(eof) {
            $halt = 1;
            last;
        }

        my @row = $csv->getline($stdin);
        # Do more stuff here
    }

    last if($halt);
}

由于 IO::Poll 使用缓冲,而像 sysread 这样的直接调用不使用(并且它们不能混合),因此轮询 STDIN 有点麻烦。我不想在没有阻塞的情况下无限调用 sysread。我需要使用 selectpoll因为我不想锤CPU。

请注意:我说的是标准输入,而不是标准输出。 $|++ 不是解决方案。

[编辑]
根据评论和其他答案更新我的问题以澄清。

写入 STDOUT(在管道的另一侧)的程序在每次写入后都会被行缓冲和刷新。每次写入都包含一个换行符,因此实际上,对于第一个程序的 STDOUT 而言,缓冲不是问题。

为了验证这是真的,我写了一个小的 C 程序,它从同一个程序中读取管道输入,并禁用 STDIN 缓冲(setvbuf 和 _IONBF)。输入立即出现在测试程序的 STDIN 中。遗憾的是,第一个程序的输出似乎不是问题。
[/编辑]

感谢您的任何见解!

附注。我已经做了大量的谷歌搜索。 This link是我找到的最接近答案的方法,但它肯定不能满足我的所有需求。

最佳答案

您实际上是在谈论其他程序的 STDOUT。解决方法是$|=1; (或等效的)在另一个程序中。

如果不能,您可以说服其他程序使用行缓冲而不是块缓冲,方法是将其 STDOUT 连接到伪 tty 而不是管道(例如,像 Expect.pm 那样)。

unix程序expect有一个工具叫 unbuffer正是这样做的。 (它是 Ubuntu 上 expect-dev 包的一部分。)只需在命令名称前加上 unbuffer .

关于无缓冲或行缓冲的 Perl STDIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23502239/

相关文章:

java - 如何在其他应用程序打开或使用文件时写入文件?

file-io - Fortran 读取语句读取超出行尾的内容

Python popen() 在要求时插入密码

c++ - C、C++、python、perl在Web开发中的作用

shell - 你最新的有用 Perl one-liner(或涉及 Perl 的管道)是什么?

perl - 如何将 MojoX::Redis 结果分配给变量?

java - (已解决)序列化(写入)充满对象的Arraylist不断抛出 "NotSerializableException"

C 读取(来自标准输入)在 0x1a 字符处停止

powershell - 如何评估来自标准输入的 PowerShell 脚本输入

perl - 一种检查已安装 perl 模块完整性的方法?