无法读取管道

The*_*chr 1 perl fork pipe

我不知道我是不是意外地删除了或者在某处输入了一个错字,但突然之间我的一些代码停止了工作.出于某种原因,从$ in中没有读取任何行.

use Win32::Job;
use IO::Handle; 

STDOUT->autoflush;

pipe my $in, my $out;

my $job = Win32::Job->new;

sub flush_pipe{
    while (defined(my $line = <$in>)) {
       chomp($line);
       print($line);

    }
}
my $pid = $job->spawn("cmd", "cmd /C \"ipconfig\"",
    {
        stdout=>$out
    }
);
flush_pipe();
Run Code Online (Sandbox Code Playgroud)

编辑:通过反复试验,我最终发现在冲洗管道之前我必须关闭$ out文件句柄.

zdi*_*dim 5

一个管道是单向的.它连接的每个进程都可以读或写.

$in有两个文件句柄,并且两个父母和子女看到他们俩.如果孩子要写和父母要读,就像你的代码一样,那么孩子必须先关闭它不会使用的句柄($out),父母必须关闭它未使用的句柄,spawn.否则你会遇到死锁.

STDOUT从模块开始一个子进程(或者更确切地说,它在Windows近似)和其重定向$out到管道的书写端,close $out.

一些非常基本的代码应该涵盖这一点

use strict;
use warnings;
use feature 'say';

pipe my $in, my $out;

my $pid = fork // die "Can't fork: $!";

if ($pid == 0) { # child
    close $in;
    print $out "hi ";         # can't read this yet (no newline) ...
    sleep 1;
    say   $out "from child";  # now the other end can read it
    close $out;
    exit;
}

# parent
close $out;

say while <$in>;
close $in;

wait;
Run Code Online (Sandbox Code Playgroud)

当您希望打印件立即可供读取器使用时(直到在代码外部缓冲)发送换行符.在执行任何其他操作之前,在每个过程中关闭管道的未使用端.

我现在无法在Windows上编写代码,但在您的代码中父必须spawn(之后flush_pipe()).

这里的术语"刷新"可以与编写器中的代码或Perl的IO缓冲区清除有关; 你的代码read_pipe只是读取管道.所以我要更改名称,$in等等.