3

Perl 5.14 来自库存 Ubuntu Precise 存储库。尝试编写一个简单的包装器来监视从一个流复制到另一个流的进度:

use IO::Handle;
while ($bufsize = read (SOURCE, $buffer, 1048576)) {
    STDERR->printflush ("Transferred $xferred of $sendsize bytes\n");
    $xferred += $bufsize;
    print TARGET $buffer;
}

这没有按预期执行(每次读取 1M 缓冲区时写入一行)。我最终看到了第一行(空白值为 $xferred),然后什么都没有,直到第 7 行和第 8 行所有内容都刷新(在 8MB 传输中)。我已经为此绞尽脑汁了好几个小时——我已经阅读了 perldocs,我已经阅读了经典的“遭受缓冲”文章,我已经尝试了从 select 和 $|++ 到 IO::Handle 到 binmode 的所有内容( STDERR, "::unix") 给你命名。我还尝试使用 IO::Handle (TARGET->flush) 对每一行刷新 TARGET。没有骰子。

有没有其他人遇到过这个?我没有任何想法了。睡一秒钟“解决”了这个问题,但显然我不想每次读取缓冲区时都睡一秒钟,这样我的进度就会在屏幕上输出!

FWIW,无论我输出到STDERR还是STDOUT,问题都是一样的。

4

1 回答 1

5

Perlread调用fread(3),不是read(2)

这意味着它通过libc并且可能正在使用比您更大的内部缓冲区;即,它获取所有要接收的数据,然后以 1MB 的增量快速将其扔给您。

如果这个猜想是正确的,解决方案可能是使用sysread,它调用read(2),而不是read

于 2013-06-24T17:48:34.783 回答