【发布时间】:2018-02-01 18:17:05
【问题描述】:
我对信号一无所知,对管道只有一点了解。
从 cmets 开始 zdim's answer here 似乎信号可能会干扰父进程和子进程之间的管道通信。
有人告诉我,如果您正在使用
IO::Select
和
sysread,
然后退出子进程
可能会以某种方式搞砸IO::Select::can_read 的行为,
特别是如果有多个子进程。
请描述在使用管道时如何处理信号?下面的代码是一个没有考虑信号的例子。
use warnings;
use strict;
use feature 'say';
use Time::HiRes qw(sleep);
use IO::Select;
my $sel = IO::Select->new;
pipe my $rd, my $wr;
$sel->add($rd);
my $pid = fork // die "Can't fork: $!"; #/
if ( $pid == 0 ) { # Child code
close $rd;
$wr->autoflush;
for ( 1..4 ) {
sleep 1;
say "\tsending data";
say $wr 'a' x ( 120 * 1024 );
}
say "\tClosing writer and exiting";
close $wr;
exit;
}
# Parent code
close $wr;
say "Forked and will read from $pid";
my @recd;
READ:
while ( 1 ) {
if ( my @ready = $sel->can_read(0) ) { # beware of signals
foreach my $handle (@ready) {
my $buff;
my $rv = sysread $handle, $buff, ( 64 * 1024 );
warn "Error reading: $!" if not defined $rv;
if ( defined $buff and $rv != 0 ) {
say "Got ", length $buff, " characters";
push @recd, length $buff;
}
last READ if $rv == 0;
}
}
else {
say "Doing else ... ";
sleep 0.5;
}
}
close $rd;
my $gone = waitpid $pid, 0;
say "Reaped pid $gone";
say "Have data: @recd"
【问题讨论】:
-
再一次,您是否愿意为此使用管道?使用用于进程间通信的文件,您将减少容量、死锁、信号和可移植性方面的麻烦。和调试(在程序结束时,您可以检查文件并查看它是否包含您期望的内容)。
-
我尝试使用管道,因为看起来我真的应该学习它们如何工作才能成为一名优秀的工程师。但相比之下,它确实显得过于复杂。我觉得我正在通过一个良好的设置取得进展,但我还没有达到我认为它应该足够可靠的舒适点
-
我相信管道也会快很多
-
但是是的,也许我会放弃这项工作:(
-
如果你对 IPC 不满意,那么切换到使用文件不会有太大帮助:会出现许多相同的问题,最后你必须意识到运行的后果在共享资源的同时并行处理。我假设你已经阅读并吸收了
perldoc perlipc?