电脑技术学习

UNIX 进程揭秘

dn001

  在此例中,父进程调用 fork,等待两秒钟,然后退出。子进程在五秒钟内继续打印其父 PID。可以看到,PPID 在父进程终止后更改为 1。Shell 提示符的返回也是非常有趣的。由于子进程在后台运行,父进程一终止,控制即返回到 Shell。

  子进程在父进程之前终止

  清单 7 与清单 6 相反——即在父进程之前终止的子进程。为更好地说明所发生的事情,进程本身中没有打印任何内容。而有趣的信息来自于进程清单。

  清单 7. 子进程在父进程之前终止

sunbox$ cat dIE2.c
#include <unistd.h>
#include <stdio.h>
int main(void) {
    int i;
    if (!fork()) {
        /* Child exits immediately*/
        _exit(0);
    }
  /* Parent waits around for a minute */
    sleep(60);
}
sunbox$ gcc die2.c -o die2
sunbox$ ./die2 &
[1] 2934
sunbox$ ps -ef | grep 2934
  sean 2934 2885  0 21:43:05 pts/1    0:00 ./die2
  sean 2935 2934  0    - ?      0:00 <defunct>
sunbox$ ps -ef | grep 2934
[1]+ Exit 199        ./die2

  die2 使用 & 操作符在后台运行,然后显示一个进程清单,并且仅显示正在运行的进程及其子进程。PID 2934 是父进程,PID 2935 是派生 (fork) 并立即终止的进程。尽管子进程提前退出,但它仍然在进程表中作为失效 (defunct) 进程存在,或称为僵死 (zombie) 进程。当父进程在 60 秒以后终止时,两个进程都消失了。

  当子进程终止时,会使用一个名为 SIGCHLD 的信号来通知其父进程。该通知的确切机制现在对您并不重要。重要的是父进程必须以某种方式确认子进程的终止。子进程从终止时起就一直处于僵死状态,直到父进程确认该信号为止。僵死进程不运行或消耗 CPU 周期;它只是占用进程表空间。当父进程终止时,内核最终能够回收未确认的子进程以及父进程。这意味着可消除僵死进程的唯一方法是终止父进程。处理僵死进程的最好方法是首先确保它们不会发生。清单 8 中的代码实现了一个处理传入的 SIGCHLD 信号的信号处理程序。

标签: