是否有任何POSIX信号可以在我的Perl程序中用于创建事件驱动编程?目前,我有多进程程序,能够交叉通信,但我的父线程只能听一次听一个孩子.
foreach (@proc) {
sysread(${$_}{'read'}, my $line, 100); #problem here
chomp($line);
print "Parent hears: $line\n";
}
Run Code Online (Sandbox Code Playgroud)
问题是父母处于持续等待状态,直到它从第一个孩子收到信号才能继续.我依靠'管道'来进行相互沟通.
我目前的解决方案非常类似于:如何使用`pipe`来促进Perl中的进程间通信?
如果可能的话,我想依靠$ SIG {...}事件或任何非CPAN解决方案.
更新:
正如Jonathan Leffler所说,kill可用于发送信号:
我的解决方案是向我的子进程发送USR1信号.此事件告诉父母听取特定的孩子.
儿童:
kill USR1 => $parentPID if($customEvent);
syswrite($parentPipe, $msg, $buffer);
#select $parentPipe; print $parentPipe $msg;
Run Code Online (Sandbox Code Playgroud)
父:
$SIG{USR1} = {
#get child pid?
sysread($array[$pid]{'childPipe'}, $msg, $buffer);
};
Run Code Online (Sandbox Code Playgroud)
更新2:解决方案
我选择了一个使用矢量方法进行非阻塞IO的选择.对于遇到此线程的人,请查看:http://docstore.mik.ua/orelly/perl/cookbook/ch07_14.htm,因为它涵盖了向量方式和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
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用select来监视通信通道(注意:如果您在 Win32 上,select 只能在套接字上使用)。
所以你可以使用这样的代码:
use IO::Select;
use IO::Handle;
...
$_->blocking(0) for @handles;
while( 1 ) {
my $s = IO::Select->new( @handles );
for my $h ( $s->can_read( 1 ) ) {
my $data = read_handle($h);
process_handle_data( $data );
}
}
sub read_handle {
my $h = shift;
my $got = '';
1 while read( $h, $got, 1024, length $got );
return $got;
}
Run Code Online (Sandbox Code Playgroud)
看一下 perlipc 中的 UDP 示例。它使用内置的 select。IO::Select与内置模块相比,我更喜欢核心模块select,它更容易阅读。
更新:您确实应该考虑使用 POE、Event 或 Coro 等事件框架。这个 perlmonks 线程中有一个非常好的选项列表。不要害怕 CPAN。
| 归档时间: |
|
| 查看次数: |
1158 次 |
| 最近记录: |