forfor时,在Windows上的Perl中STDOUT的IO句柄?

时间:2011-01-18 05:35:25

标签: perl ipc fork

我有以下问题: 我尝试将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是孩子标准输出的句柄。

1 个答案:

答案 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);
}