如何在Perl中从管道进行非阻塞读取?

时间:2010-09-22 21:45:45

标签: windows perl asynchronous pipe

我有一个程序正在调用另一个程序并处理孩子的输出,即:

my $pid = open($handle, "$commandPath $options |");

现在我尝试了几种不同的方式从句柄中读取而没有阻塞,但很少或没有成功。

我发现了相关的问题:

但是他们遇到了这些问题:

  • ioctl一直崩溃perl
  • sysread阻塞0字节(常见)

我不确定如何解决这个问题。

1 个答案:

答案 0 :(得分:4)

管道在Windows上不像在Unix-y系统上那样功能。你不能在它们上使用4参数select,默认容量微乎其微。

最好尝试基于套接字或文件的解决方法。

$pid = fork();
if (defined($pid) && $pid == 0) {
    exit system("$commandPath $options > $someTemporaryFile");
}
open($handle, "<$someTemporaryFile");

现在你需要处理更多的蠕虫 - 定期运行waitpid来检查后台进程何时停止创建输出,在你读取之后调用seek $handle,0,1来清除eof条件$handle,清理临时文件,但是有效。

我已经编写了Forks::Super模块来处理这样的问题(和许多其他问题)。对于这个问题,你可以像

一样使用它
use Forks::Super;
my $pid = fork { cmd => "$commandPath $options", child_fh => "out" };
my $job = Forks::Super::Job::get($pid);
while (!$job->is_complete) {
    @someInputToProcess = $job->read_stdout();
    ... process input ...
    ... optional sleep here so you don't consume CPU waiting for input ...
}
waitpid $pid, 0;
@theLastInputToProcess = $job->read_stdout();