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

发布于 2024-09-24 12:51:48 字数 585 浏览 6 评论 0原文

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

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

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

我发现相关问题:

但他们遇到了以下问题:

  • ioctl 始终
  • 在 0 字节上使 perl sysread 块崩溃(常见情况)

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

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
  • sysread blocks on 0 bytes (a common occurrence)

I'm not sure how to go about solving this problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最初的梦 2024-10-01 12:51:48

管道在 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$handle 读取后清除 eof 条件,清理临时文件,但它有效。

我已将 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();

Pipes are not as functional on Windows as they are on Unix-y systems. You can't use the 4-argument select on them and the default capacity is 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.

I have written the Forks::Super module to deal with issues like this (and many others). 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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文