2014-08-29 18 views
4

我正试图在使用信号的进程之间实现通信。首先,家长启动子流程,完成一些工作,然后等待孩子的消息,然后再次给孩子发信号,以便孩子可以继续处理等等。在进程间发送消息在Perl中

我不知道什么是实现这个正确的做法,但这里是我第一次尝试:

use warnings; 
use strict; 
use feature qw(say); 

my $forever=1000000; 
my $parPID=$$; 
my $child = fork(); 
if($child == 0){ 
    runSubProc($parPID,$forever); 
} 

$SIG{"USR1"}=sub { 
    say "Parent: got signal 1"; 
    $SIG{"USR1"}=sub { 
    say "Parent: got signal 2"; 
    exit 0; 
    }; 
    sleep 5; 
    kill 'USR1', $child; 
    sleep $forever; 
}; 

say "Waiting for child processes.."; 
sleep $forever; 


sub runSubProc { 
    my ($parPID,$forever)[email protected]_; 

    $SIG{"USR1"}=sub { 
    say "Child: got signal 1"; 
    $SIG{"USR1"}=sub { 
     say "Child: got signal 2"; 
     exit 0; 
    }; 
    sleep 7; 
    kill 'USR1', $parPID; 
    sleep $forever; 
    }; 
    sleep 5; 
    kill 'USR1', $parPID; 
    sleep $forever; 
} 

这不起作用,输出结果是:

Waiting for child processes.. 
Parent: got signal 1 
Child: got signal 1 

,然后将其挂起..

+0

尝试使用'strace -fTt。/ scriptname'运行。我猜想你的信号不止一次被解雇 - 记住'信号处理器'是救市,而不是重新进入。 我认为你的问题的核心将是 - 你正在信号处理程序中重新定义你的'信号处理程序'。但我会有一个小提琴,看看我能否成功。 – Sobrique 2014-08-29 14:23:06

回答

6

根本原因是您的信号处理程序中的sleep $forever。因为你的进程是已经处理'SIGUSR1',所以下一个kill信号没有得到处理 - 这是为了避免信号中断信号的各种弊端。避免任何会阻止你的处理程序。

这似乎工作:

$SIG{'USR1'} = \&handle_USR1; 

my $ppid  = $$; 
my $child_pid = fork(); 

sub handle_USR1 { 
    if ($signalled++) { print "$$: got second USR1\n"; exit 0 } 

    print "$$: caught SIGUSR1\n"; 
    if (not $child_pid) { 
     print "$$: Child got a SIGUSR1\n"; 
     sleep 7; 
     print "$$: (child) sending signal to $ppid\n"; 
     kill 'USR1', $ppid; 
    } else { 
     print "$$: (parent) got USR1\n"; 
     sleep 5; 
     print "$$: parent signalling child\n"; 
     kill 'USR1', $child_pid; 
    } 
} 

if ($child_pid) { 
    print "$$ (parent) waiting\n"; 
    sleep 500; 
} else { 
    print "$$: (child) waiting\n"; 
    sleep 5; 
    print "$$: Child signalling $ppid\n"; 
    kill 'USR1', $ppid; 
    sleep 500; 
} 

您可能需要重新洗牌一点,但最核心的一点是 - 在飞行中重新定义你的信号处理,更特别的是通过将睡在有“拖延”他们将打破信号机制。

+0

本周你做出了一些非常不错的贡献。荣誉 – Miller 2014-08-30 00:07:36

+0

感谢您的好解释!信号后,似乎睡眠500没有继续。信号处理程序运行后,程序将退出。 – 2014-08-30 06:06:19

+0

不再在我的Unix机器上,所以无法验证(Windows不让我使用SIGUSR1)。但是这可能是因为'kill'中断了'sleep',然后进程正常退出(因为睡眠是最后一行)。所以你可能需要坐在一个循环中。 http://perldoc.perl.org/functions/sleep.html - 它不会回到睡眠子程序中。 – Sobrique 2014-08-30 09:29:17