如何在Windows上读取非阻塞IPC? [英] How do I do a non-blocking IPC read on Windows?

查看:108
本文介绍了如何在Windows上读取非阻塞IPC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Perl脚本,该脚本使用外部工具(cleartool)来收集有关文件列表的信息.我想使用IPC来避免为每个文件生成新进程:

I have a Perl script that uses an external tool (cleartool) to gather information about a list of files. I want to use IPC to avoid spawning a new process for each file:

use IPC::Open2;
my ($cin, $cout);
my $child = open2($cout, $cin, 'cleartool');

返回单行的命令效果很好.例如

Commands that return single-lines work well. e.g.

print $cin "describe -short $file\n";
my $description = <$cout>;

返回多行的命令使我陷入僵局,以了解如何消耗整个响应而不会因阻塞读取而挂断:

Commands that return multiple lines have me at a dead end for how to consume the entire response without getting hung up by a blocking read:

print $cin "lshistory $file\n";
# read and process $cout...

我试图通过fcntl为非阻塞读取设置文件句柄:

I've tried to set the filehandle for non-blocking reads via fcntl:

use Fcntl;
my $flags = '';
fcntl($cout, F_GETFL, $flags);
$flags |= O_NONBLOCK;
fcntl($cout, F_SETFL, $flags);

但是Fcntl死于消息您的供应商尚未定义Fcntl宏F_GETFL."

but Fcntl dies with the message "Your vendor has not defined Fcntl macro F_GETFL."

我尝试使用IO :: Handle设置$cout->blocking(0),但是失败(它返回undef并将$!设置为未知错误").

I've tried using IO::Handle to set $cout->blocking(0) but that fails (it returns undef and sets $! to "Unknown error").

我尝试使用select在尝试读取之前确定是否有可用数据:

I've tried to use select to determine if there's data available before attempting to read:

my $rfd = '';
vec($rfd, fileno($cout), 1) = 1;
while (select($rfd, undef, undef, 0) >= 0) {
    my $n = read($cout, $buffer, 1024);
    print "Read $n bytes\n";
    # do something with $buffer...
}

但是挂起却没有阅读任何内容.有谁知道如何使它工作(在Windows上)?

but that hangs without ever reading anything. Does anyone know how to make this work (on Windows)?

推荐答案

select仅适用Windows中的套接字上.看起来IPC :: OpenX使用普通的文件句柄,因此您将无法将select与它创建的句柄一起使用.

select only works on sockets in Windows. It looks like IPC::OpenX uses normal filehandles, so you won't be able to use select with the handles it creates.

如果不需要超时/检测到select提供的活动,则可以将句柄设置为非阻塞状态,而只需按常规进行读取或写入.

If you don't need the timeout/detection of activity that select provides, you can set the handles to be non-blocking and just read or write as per normal.

如果您需要更多细微的控制,则 IPC :: Run 可能会很好为你.

If you need more nuanced control, IPC::Run may work well for you.

您还可以考虑创建一个socketpair并将这些句柄与您的子进程一起使用.较新的perls(5.8及更高版本)在Windows上使用TCP套接字支持socketpair仿真.

You could also look at creating a socketpair and use those handles with your child processes. Newer perls (5.8 and up) support socketpair emulation on Windows using TCP sockets.

如果您尝试克隆STDOUTSTDERR来运行没有控制台的程序(即,它是用wperl而不是perl启动的),则您将无法通过STDIO获取数据.

If you try to clone STDOUT and STDERR for a program that runs without a console (ie it is started with wperl, instead of perl), you won't be able to get data through STDIO.

在实践中,这对我来说在几个项目上都是一个巨大的痛苦.我发现最好的方法是编写子进程以通过TCP连接到父服务器.如果您不控制子进程,请查看IPC::Runsocketpair.

In practice this has been a huge pain for me on several projects. What I found worked best was to write the child process to connect to the parent server via TCP. If you don't control the child processes, look at IPC::Run or socketpair.

这篇关于如何在Windows上读取非阻塞IPC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆