当后台进程在Perl中终止时,如何通知我?

当后台进程在Perl中终止时,如何通知我?,perl,fork,Perl,Fork,我编写了一个Perl程序,它在子进程中分叉并调用后台程序,并且有一个无休止的while循环,它在父进程中执行一些操作。现在,当子进程中的后台程序终止时,应保留while循环: $pid = fork(); if ( !$pid ) { exec( "program args" ); } else { while ( 1 ) { # do something # needs help: if program terminated, break

我编写了一个Perl程序,它在子进程中分叉并调用后台程序,并且有一个无休止的while循环,它在父进程中执行一些操作。现在,当子进程中的后台程序终止时,应保留while循环:

$pid = fork();
if ( !$pid ) {
    exec( "program args" );
} else {
    while ( 1 ) {
        # do something

        # needs help: if program terminated, break
    }
}

我猜,exec()正在阻塞,因此在程序退出之前它不会返回,但我可能错了。

好吧,
fork
将子进程的PID(您在代码中尽职尽责地检索)提供给父进程。这正是父母可以照顾孩子的原因


要在循环终止时离开循环,可以使用
kill 0$pid
检查子循环是否仍然存在。请参见
perldoc-f kill

您需要一个信号处理程序来处理当子进程退出时父进程被发送的CHLD信号。(有关perl中信号处理的更多详细信息,请参见
perldoc-perlipc

您可以在else循环中执行以下操作来获取子进程。


或者,您可以将
$SIG{CHLD}='IGNORE'
设置为不担心子进程变成僵尸。

根据您的应用程序,您可以不时检查子进程是否结束,父进程是否可以完成。您可以将posix waitpid()与WNOHANG一起使用,以执行无阻塞等待,或者发出信号检查您的孩子是否仍在运行,或者可以使用管道(在关闭时检查)。我个人会使用waitpid()。perlipc中有一个很好的例子解释

-1不,该程序之前使用了
fork
,因此只有一个子进程将使用
exec
,这是正确的。问题是该进程正在变成僵尸,因此该命令仍然返回true。不过,当设置$SIG{CHLD}='IGNORE'(请参阅下一个答案)时,该命令仍然有效。感谢您的提示。我把它和上面的提示结合起来了
...
} else {
    $SIG{CHLD} = \&reaper
}

# hash to store exit status of child processes
our %child;    
sub reaper {
    my $x;
    while (($x = waitpid(-1,WNOHANG)) >0) {
        $child{$x} = $? >> 8;
    }
}