2014-08-29 2 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

답변

6

근본 원인은 신호 처리기 내에 sleep $forever입니다. 귀하의 프로세스가 이기 때문에 이미에 'SIGUSR1'을 처리하면 다음 킬 신호가 처리되지 않습니다. 이것은 신호를 방해하는 신호로 모든 종류의 불안을 피하기위한 것입니다. 핸들러 내에서 차단되는 것을 피하십시오.

가 작동하는 것 같다 :

$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

+0

좋은 설명 주셔서 감사합니다! 'sleep 500'이 신호 다음에 계속되지 않는 것 같습니다. 신호 처리기가 실행 된 후 프로그램이 종료됩니다. –

+0

유닉스 박스에 더 이상 존재하지 않으므로 확인할 수 없습니다 (Windows에서 SIGUSR1을 사용할 수 없음). 하지만 아마'kill '이'sleep'을 방해하고 프로세스가 정상적으로 종료하기 때문에 (아마 sleep이 마지막 줄이기 때문일 것입니다). 그래서 루프에 앉아 있어야 할 수도 있습니다. http://perldoc.perl.org/functions/sleep.html - 수면 서브 루틴으로 '돌아 가지 않을 것'입니다. – Sobrique