作者:川人是天下的盐恋歌_334 | 来源:互联网 | 2023-01-03 20:55
我不知道我是不是意外地删除了或者在某处输入了一个错字,但突然之间我的一些代码停止了工作.出于某种原因,从$ 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文件句柄.
1> zdim..:
一个管道是单向的.它连接的每个进程都可以读或写.
后$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;
当您希望打印件立即可供读取器使用时(直到在代码外部缓冲)发送换行符.在执行任何其他操作之前,在每个过程中关闭管道的未使用端.
我现在无法在Windows上编写代码,但在您的代码中父必须spawn
(之后flush_pipe()
).
这里的术语"刷新"可以与编写器中的代码或Perl的IO缓冲区清除有关; 你的代码read_pipe
只是读取管道.所以我要更改名称,$in
等等.