我有以下问题: 我尝试将perl脚本移植到Windows。 该脚本经常自行分叉,并使用此代码进行分叉:
sub sub_fork {
my ( $subref, @args ) = @_;
my $fh = new IO::Handle;
my $pid = open( $fh, "-|" );
if ( $pid ) { # parent
return ( $fh, $pid );
}
else {
&$subref( @args );
exit;
}
}
Windows不喜欢“ - |”它似乎。 我实际上不知道这是什么,作为一个windows-guy,但这里有一些有趣的东西:http://www.cs.tufts.edu/comp/150PPP/notes/perl_ipc.php(搜索“Fancy opens”) 代码在脚本中经常使用,所以我想用一个完全相同的替换sub,这意味着它返回$ fh,$ pid,其中$ fh是孩子标准输出的句柄。
答案 0 :(得分:4)
此结构用于interprocess communication,专门用于创建从新后台进程的标准输出中读取的文件句柄。
my $pid = open my $fh, "-|";
if ($pid == 0) { # child
print "Hello world\n";
exit;
}
print <$fh>; # Hello world\n
请参阅perlipc
doc了解这种结构有用的原因。
这仅适用于具有“true fork”的系统,但不包括Windows。 Windows解决方法将涉及使用socketpair
为IPC创建一些套接字(pipe
,唉,不能胜任Windows上的任务)。这样的事情会起作用:
sub sub_fork {
my ($subref, @args) = @_;
use Socket;
my ($READER, $WRITER);
socketpair $READER, $WRITER, AF_UNIX, SOCK_STREAM, PF_UNSPEC;
shutdown($READER,1); # close write channel for $READER
shutdown($WRITER,0); # and read channel for $WRITER
my $pid = fork();
if ( $pid ) {
return ($READER, $pid);
} else {
close STDOUT;
open STDOUT, '>&' . fileno($WRITER); # dup STDOUT to print to $WRITER
&$subref(@args);
# both of these steps are required before you exit the child
close STDOUT;
shutdown($WRITER,1);
exit;
}
}
Forks::Super
模块(我写的)也可以在Windows中解决这个问题。
use Forks::Super;
sub sub_fork {
my ($subref, @args) = @_;
my $pid = fork { child_fh => 'out' }; # make child's STDOUT available
if ($pid != 0) {
return ($Forks::Super::CHILD_STDOUT{$pid}, $pid);
#alternate: return ($pid->{child_stdout}, $pid);
} else {
&$subref(@args);
exit;
}
}
甚至更加苛刻
use Forks::Super;
sub sub_fork {
my ($subref, @args) = @_;
my $pid = fork {
child_fh => 'out',
sub => $subref, args => \@args # run $subref->(@args) in child
};
return ($Forks::Super::CHILD_STDOUT{$pid}, $pid);
}