2010-09-22 92 views
2

我有一个程序,它被调用其他程序和处理孩子的输出,即:如何在Perl中对管道进行非阻塞式读取?

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

现在,我已经尝试了几种不同的方法从手柄到读不与很少或根本没有成功的阻止。

我找到的相关问题:

但他们从问题的困扰:

  • ioctl一贯崩溃的perl
  • sysread 0字节的块(常见)

我不知道如何去解决这个问题。

+0

这是Windows? – mob 2010-09-22 21:51:58

+0

请参阅[这个答案](http://stackoverflow.com/questions/1530592/why-does-my-perl-sysread-block-when-reading-from-a-socket/1532251#1532251) - 使用'选择()'来确定是否有可供读取的数据。 – Ether 2010-09-22 21:52:58

+0

@其他选择不能在窗口上的文件句柄上工作 – tzenes 2010-09-22 21:56:35

回答

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

@mobrule我的理解是我不能在文件句柄上使用select,所以这只是重新创建了我现在使用的相同问题。 – tzenes 2010-09-22 22:02:15

+0

您不需要在文件句柄上使用select。读取一个耗尽的文件句柄将会返回'undef'而不会阻塞,然后可以调用'seek HANDLE,0,1'来清除eof条件并再次读取它。 – mob 2010-09-22 22:05:29

+0

@mob我会不得不寻求我已经读了多远?或者它能处理? – tzenes 2010-09-22 22:08:00