简体   繁体   English

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

[英]How do I do a non-blocking read from a pipe in Perl?

I have a program which is calling another program and processing the child's output, ie: 我有一个程序正在调用另一个程序并处理孩子的输出,即:

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

Now I've tried a couple different ways to read from the handle without blocking with little or no success. 现在,我尝试了几种不同的方式从句柄读取内容,但没有成功或很少成功。

I found related questions: 我发现了相关问题:

But they suffer from the problems: 但是他们遭受了以下问题:

  • ioctl consistently crashes perl ioctl持续崩溃perl
  • sysread blocks on 0 bytes (a common occurrence) sysread块为0字节(常见情况)

I'm not sure how to go about solving this problem. 我不确定如何解决这个问题。

Pipes are not as functional on Windows as they are on Unix-y systems. 管道在Windows上的功能不如Unix-y系统上的。 You can't use the 4-argument select on them and the default capacity is miniscule. 您不能在其上使用4参数select ,默认容量为miniscule。

You are better off trying a socket or file based workaround. 您最好尝试使用基于套接字或文件的解决方法。

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

Now you have a couple more cans of worms to deal with -- running waitpid periodically to check when the background process has stopped creating output, calling seek $handle,0,1 to clear the eof condition after you read from $handle , cleaning up the temporary file, but it works. 现在,您还有更多罐蠕虫需要处理-定期运行waitpid来检查后台进程何时停止创建输出,从$handle读取后,调用seek $handle,0,1以清除eof条件,然后进行清理临时文件,但可以。

I have written the Forks::Super module to deal with issues like this (and many others). 我已经编写了Forks::Super模块来处理此类问题(以及许多其他问题)。 For this problem you would use it like 对于这个问题,你会像

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM