由SIGCHLD终止的Perl睡眠

由SIGCHLD终止的Perl睡眠,perl,Perl,输出: #!/usr/bin/perl use POSIX ":sys_wait_h"; $SIG{CHLD} = \&REAPER; sub REAPER { my $pid; while (($pid = waitpid(-1, WNOHANG)) > 0) { print "where is here,$pid\n"; } } sub child { print "I'm child, pid=$$.\n"; sleep 2; } $l

输出:

#!/usr/bin/perl

use POSIX ":sys_wait_h";
$SIG{CHLD} = \&REAPER;

sub REAPER {
  my $pid;
  while (($pid = waitpid(-1, WNOHANG)) > 0) {
      print "where is here,$pid\n";
  }
}

sub child {
  print "I'm child, pid=$$.\n";
  sleep 2;
}

$lid = fork();
if ($lid == 0) {
    &child;
    exit;
} else {
    sleep 1000;
    print "I am parent, child pid : $lid\n";
}
上面是我的Perl脚本。输出是正确的,但奇怪的是,它在最后一次输出后立即打印
I am parent,child pid:11839
。为什么
sleep 1000
没有任何效果?

请始终
使用严格的
使用警告
,并在定义点使用
my
声明您的符号。这一点尤其适用于请求帮助时,因为这些措施可能会暴露出容易被忽略的简单错误

sleep
通过使用
setitimer
在指定的间隔后请求
SIGALRM
,然后
pause
暂停进程,直到收到信号为止

但是如果先出现一个
SIGCHLD
,这也会唤醒进程

无法设置信号掩码以防止出现这种情况,否则将无法维修
SIGCHLD
,这是:“如果进程接收到信号,可能会中断”。整个要点是允许信号处理程序运行。如果还没到起床的时间,就回去睡觉吧

I'm child, pid=11839.
where is here,11839
I am parent, child pid : 11839
使用时间::雇佣qw(时间睡眠);#可选。
子未调整睡眠(美元){
我的$sleep_til=时间+$\u[0];
对于(;;){
我的$sleep\u dur=时间-$sleep\u til;

最后,如果$sleep_dur这不是
sleep
的实现方式,在这十年来的大多数操作系统/Perl中,或者在内核中。请参阅@ZacB:我正在查看Perl v5.24的C源代码,您的评论似乎不公平。请添加一个答案,正确定义Perl
sleep
调用在您眼中的工作方式。注意,它没有调用
usleep
是您链接到的。@ZacB那么它是如何实现的?我想知道,如果不是这样的话。您提供的链接只是
usleep
的手册页,它没有告诉我Perl是如何实现自己的。Perl的页面实际上暗示了
setitimer
。请注意,
usleep
来自前面提到的模块ed似乎没有使用这个系统调用(请参阅模块的文档)。您能提供一些文档或指针吗?请参阅strace perl-e'sleep(10)“
。在我使用过的平台上,不会调用
alarm
setitimer
,也不会发送信号;相反,会调用
nanosleep
和朋友。此外,因为每个进程只有一个
alarm
/
setitimer
时钟(至少在Unix中),实现带有报警的
睡眠
会破坏用户设置的报警,而这不会发生;请参阅
time perl-e“报警(2);睡眠(10);”
use Time::HiRes qw( time sleep );  # Optional.

sub unint_sleep($) {
    my $sleep_til = time + $_[0];
    for (;;) {
        my $sleep_dur = time - $sleep_til;
        last if $sleep_dur <= 0;
        sleep($sleep_dur);
    }
}