1
我正在嘗試使用管道和select
命令來實現進程間通信。這是第一次嘗試:Perl選擇返回「壞文件描述符」錯誤
use warnings;
use strict;
use feature qw(say);
use IO::Select;
use IO::Handle;
my @rh;
my %childs;
my $numChilds=2;
$SIG{CHLD}='IGNORE'; #Reap childs automatically
for my $i (1..$numChilds) {
pipe(my $pread, my $pwrite);
push(@rh,$pread);
$pwrite->autoflush(1);
my $child = fork();
if ($child==0) {
runChild($i,$pwrite);
}
$childs{$pread->fileno()}={pid=>$child,id=>$i,i=>0};
}
my $sel = IO::Select->new(@rh);
while (1) {
say "Running select..";
my @ready = $sel->can_read;
last if (! @ready);
for my $fh (@ready) {
say "Processing file descriptor ".($fh->fileno());
chomp(my $line=<$fh>);
my $fd=$fh->fileno();
my $child=$childs{$fd}->{id};
say "Got line: \"$line\"..";
my $nmsg=($childs{$fd}->{i})+1;
if ($nmsg==2) {
$fh->close();
$sel->remove($fh);
say "Select count: ".($sel->count());
say "Closed fh $child..";
} else {
$childs{$fd}->{i}=$nmsg;
}
}
}
say "Done.";
sub someSeconds { return int(rand(4))+3; }
sub runChild {
my ($i, $pipe)[email protected]_;
sleep (someSeconds());
print $pipe "Child $i says: A\n";
sleep (someSeconds());
print $pipe "Child $i says: B\n";
exit 0;
}
輸出是:
Running select..
Processing file descriptor 4
Got line: "Child 2 says: A"..
Running select..
Processing file descriptor 3
Got line: "Child 1 says: A"..
Running select..
Processing file descriptor 4
Got line: "Child 2 says: B"..
Select count: 1
Closed fh 2..
Running select..
Done.
的問題是,從孩子1的最後一條消息是缺少Got line: "Child 1 says: B"
。
我跑strace prog.pl
這些都給:
select(8, [3 4], NULL, NULL, NULL) = -1 EBADF (Bad file descriptor)
上的最後一個電話
select
...
好的,但我沒有那麼做嗎? – 2014-08-30 10:48:10
因爲你在做''fh-> close()'之前是'$ sel-> remove($ fh)',所以你在關閉描述符之前將它從select中移除。它一定是相反的。 – 2014-08-30 11:34:00
謝謝Steffen,它現在完美的工作! – 2014-08-30 11:38:37