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

tze*_*nes 3 windows perl asynchronous pipe

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

my $pid = open($handle, "$commandPath $options |");
Run Code Online (Sandbox Code Playgroud)

现在我尝试了几种不同的方法来从句柄读取而不阻塞,但几乎没有成功。

我找到了相关问题:

但他们却面临着以下问题:

  • ioctlPerl 持续崩溃
  • sysread0 字节阻塞(常见情况)

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

mob*_*mob 5

管道在 Windows 上的功能不如在 Unix-y 系统上的功能。您不能对select它们使用 4 个参数,并且默认容量很小。

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

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

现在您还有更多的蠕虫罐头需要处理——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();
Run Code Online (Sandbox Code Playgroud)

  • @tzense - 请参阅“perldoc -feek”,特别是如何模拟“tail-f”的示例 (2认同)