【发布时间】:2011-02-03 22:18:25
【问题描述】:
是否有任何 POSIX 信号可以在我的 Perl 程序中用于创建事件驱动编程?目前,我有能够交叉通信的多进程程序,但我的父线程一次只能听一个孩子。
foreach (@proc) {
sysread(${$_}{'read'}, my $line, 100); #problem here
chomp($line);
print "Parent hears: $line\n";
}
问题是父母处于持续等待状态,直到它收到第一个孩子的信号才能继续。我依靠“管道”进行交互。
我目前的解决方案非常类似于:How can I use `pipe` to facilitate interprocess communication in Perl?
如果可能,我想依赖 $SIG{...} 事件或任何非 CPAN 解决方案。
更新:
正如 Jonathan Leffler 所说,kill 可用于发送信号:
kill USR1 => $$; # send myself a SIGUSR1
我的解决方案是向我的子进程发送一个 USR1 信号。此事件告诉父母听特定的孩子。
孩子:
kill USR1 => $parentPID if($customEvent);
syswrite($parentPipe, $msg, $buffer);
#select $parentPipe; print $parentPipe $msg;
父母:
$SIG{USR1} = {
#get child pid?
sysread($array[$pid]{'childPipe'}, $msg, $buffer);
};
- 但是我如何获得向父级发出信号的源/子 pid? 让孩子在其信息中表明自己的身份。
- 如果两个孩子同时发出 USR1 信号会怎样?
更新 2:解决方案
我选择了一个使用矢量方法进行非阻塞 IO 的选择。 对于遇到此线程的人,请查看:Perl Cookbook: 7.22. Reading from Many Filehandles Without Blocking,因为它涵盖了向量方式和 IO::Select 模块。我知道 IO::Select 模块会更优雅,但我对学习 Perl 的新机制更感兴趣。谢谢大家的帮助。
发挥:
$rin = '';
# repeat next line for all filehandles to poll
vec($rin, fileno(FH1), 1) = 1;
vec($rin, fileno(FH2), 1) = 1;
vec($rin, fileno(FH3), 1) = 1;
$nfound = select($rout=$rin, undef, undef, 0);
if ($nfound) {
# input waiting on one or more of those 3 filehandles
if (vec($rout,fileno(FH1),1)) {
# do something with FH1
}
if (vec($rout,fileno(FH2),1)) {
# do something with FH2
}
if (vec($rout,fileno(FH3),1)) {
# do something with FH3
}
}
【问题讨论】:
-
你知道,你可以把这些东西写到管道里……不需要为这些东西发送信号。在父级中,在读取前使用“选择”。
-
您的意思是
process还是thread?差别很大。 -
我在使用“select”和 运算符时遇到的问题是它等待当前选定的子进程响应并忽略所有其他子进程,直到它得到响应。
-
好吧,不要使用 。使用带有非阻塞标志的 sysread。或者不要这样做,并使用适当的框架。
-
@Shiftbit 不是那个选择,另一个选择。
标签: perl ipc posix signals unix