Эта конструкция используется для межпроцессного взаимодействия , в частности, для создания дескриптора файла, который читает стандартный вывод нового фонового процесса.
my $pid = open my $fh, "-|";
if ($pid == 0) { # child
print "Hello world\n";
exit;
}
print <$fh>; # Hello world\n
См. perlipc
doc по некоторым причинам, почему эта конструкция полезна.
Однако это работает только в системах с "истинной вилкой",что исключает 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);
}