我不知道我是不是意外地删除了某个地方的错误或突然插入错误,但突然之间我的一些代码停止了工作。由于某些原因,从$ 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();
编辑: 通过反复试验,我最终发现在冲洗管道之前我必须关闭$ out文件句柄。
答案 0 :(得分:5)
管道是单向的。它连接的每个进程都可以读或写。
pipe之后你有两个文件句柄,父母和孩子都看到了它们。如果孩子要写和父母要读,就像你的代码一样,那么孩子必须先关闭它不会使用的句柄($in
),父母必须关闭其未使用的句柄,{{1 }}。否则你将have deadlocks。
模块中的$out
启动子进程(或者更确切地说是Windows近似)并将其spawn
重定向到管道的写入端STDOUT
。< / p>
一些非常基本的代码应该涵盖这个
$out
当您希望打印件立即可供读取器使用时(最多在代码外部缓冲)发送换行符。在执行任何其他操作之前,在每个过程中关闭管道的未使用端。
我现在无法在Windows上编写代码,但在您的代码中,父代必须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;
(在close $out
之后)。
这里的术语“刷新”可以与编写器中的代码或Perl清除IO缓冲区有关; spawn
中的代码只是读取管道。所以我将这个名称更改为flush_pipe()
等。