Q:什么是僵尸进程?
A:子进程在结束运行后,父进程未进行相应处理,就成为了僵尸进程。

僵尸进程的产生有几下几种原因:

  • 父进程未 wait 子进程。
  • 子进程发送信号 SIGCHLD 给父进程,但是父进程没有理睬。
  • 其它原因

总之,父进程不负责的情况下,就可能会产生僵尸进程。

下面我们用代码来演示下:

<?php

$pid = pcntl_fork();
if ($pid === -1) {
    exit('无法创建子进程');
} elseif ($pid > 0) {
    // 父进程
    $pid = getmypid();
    echo "我是父进程:{$pid}\n";
    // 休眠20秒
    sleep(20);
    echo "父进程:拜拜咯\n";
} else {
    // 这里是子进程
    $pid = getmypid();
    echo "我是子进程:{$pid}\n";
    echo "啊,作为子进程的我结束了\n";
}

代码中,父进程休眠了20秒的时间,子进程输出两句话,直接退出了。

我们执行下:

php process4.php
我是父进程:17482
我是子进程:17483
啊,作为子进程的我结束了

利用 ps aux |grep 17483 看下:

xiaoteng         17483   0.0  0.0        0      0 s000  Z+   10:24上午   0:00.00 (php)

可以看到,PID=17483的进程状态为 Z+ 也就是僵尸进程的意思。

Q:那如何避免僵尸进程的出现呢?
A:wait 子进程

<?php

$pid = pcntl_fork();
if ($pid === -1) {
    exit('无法创建子进程');
} elseif ($pid > 0) {
    // 父进程
    $pid = getmypid();
    echo "我是父进程:{$pid}\n";
    pcntl_wait($status);
    echo "子进程的退出代码:{$status}\n";
    echo "父进程:拜拜咯\n";
} else {
    // 这里是子进程
    $pid = getmypid();
    echo "我是子进程:{$pid}\n";
    echo "啊,作为子进程的我结束了\n";
}

wait 到子进程的退出信号后,子进程就安全的退出了,释放出了资源,也就不会成为僵尸进程存在,占用系统资源。

Q:如何杀死僵尸进程呢?
A:僵尸进程无法通过kill干掉的,所以我们可以先干掉僵尸进程的父进程,让TA被1号进程接管,然后让系统会处理掉TA。