如何在Windows上进行非阻塞IPC读取?

Mic*_*man 6 windows perl ipc

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

use IPC::Open2;
my ($cin, $cout);
my $child = open2($cout, $cin, 'cleartool');
Run Code Online (Sandbox Code Playgroud)

返回单行的命令运行良好.例如

print $cin "describe -short $file\n";
my $description = <$cout>;
Run Code Online (Sandbox Code Playgroud)

返回多行的命令使我处于死胡同,以便如何使用整个响应而不会被阻塞读取挂起:

print $cin "lshistory $file\n";
# read and process $cout...
Run Code Online (Sandbox Code Playgroud)

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

use Fcntl;
my $flags = '';
fcntl($cout, F_GETFL, $flags);
$flags |= O_NONBLOCK;
fcntl($cout, F_SETFL, $flags);
Run Code Online (Sandbox Code Playgroud)

但是Fcntl的消息是"你的供应商还没有定义Fcntl宏F_GETFL".

我已经尝试使用IO :: Handle进行设置$cout->blocking(0)但失败了(它返回undef并设置$!为"Unknown error").

select在尝试阅读之前,我曾试图确定是否有可用的数据:

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...
}
Run Code Online (Sandbox Code Playgroud)

但是没有读过任何东西就挂了.有谁知道如何使这项工作(在Windows上)?

dao*_*oad 5

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

如果您不需要select提供的活动的超时/检测,则可以将句柄设置为非阻塞,并按正常方式读取或写入.

如果您需要更细微的控制,IPC :: Run可能会很适合您.

您还可以查看创建socketpair并使用子进程的句柄.较新的perls(5.8及更高版本)支持socketpair使用TCP套接字在Windows上进行仿真.

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

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