只触发两次信号处理程序就能收走5个子进程,其中第一次触发收走了3个子进程,第二次触发收走了2个子进程,是因为waitpid会返回所有等待到的子进程pid,第一次等待到了3个子进程的退出,第二次等待到了2个子进程的退出。
那么为什么system()中的ps退出时没有被SIGCHLD信号处理程序中的waitpid收走?这是因为system()函数自身就带有了wait阻塞函数,它自己会收走经过它fork出来的子进程,使得虽然ps的退出触发了SIGCHLD,但ps的退出状态值已经清空了,无法被信号处理程序中的waitpid处理。
fork两次收掉僵尸进程代码如下:
#!/usr/bin/env perl use strict; use warnings; defined(my $pid = fork) or die "fork failed: $!"; unless($pid){ # 第一个子进程 # 继续fork一个孙子进程:第二个子进程 defined(my $kid = fork) or die "fork failed: $!"; if($kid){ # 第一个子进程5秒后退出 sleep 5; exit 0; } # 孙子进程 sleep(10); print "second child, ppid=",getppid(),"\n"; exit 0; } # 为第一个子进程收尸 (waitpid $pid, 0 == $pid) or die "waitpid error: $!"; exit 0;上面的代码中,在5秒后第一个子进程退出并被父进程收尸,第二个进程将成为孤儿进程被pid=1的进程收养。