**Linux 知识补充 -- 守护进程的编写及使用方法 - 03 守护进程再次分裂子进程(僵尸进程的处理)**
1652270 **冯舜**
## 写 `test3-1.c`
编辑 `test3-1.c` 的内容:
~~~~~~~~~~~~~C
~~~~~~~~~~~~~
编译运行之, 等到输出全为 `main` 后, 其输出如下:
!![3pids,`test3-1` 的输出]
## 子进程和守护进程间的 PID 关联
从上面的输出内容来看, 子进程的 PID 基本上是连续的, 最小的子进程 PID 由守护进程的 PID + 1 得到.
## 僵尸进程
在 `test3-1` 的运行输出全为 `main` 后, 在另一终端使用 `ps -f f -C test3-1` 查看所有有关进程信息, 如//3defunct//.
!![3defunct,用 `ps` 查看所有相关进程信息]
发现所有的子进程有 `` 标记, 且 `STAT` 中显示其状态为 `Z+`; 说明它们是僵尸进程.
有一些进程在 `fork()` 后不执行 `wait` 等待子进程结束, 僵尸进程通常就是它们的子进程结束后所进入的状态. 它们除了占用系统的进程描述符之外, 已经不再占用其他任何空间 (已经"死了"), 但由于父进程没有正确响应 `SIGCHLD` 信号, 进而调用 `wait()` 对其子进程进行清理, 故这些子进程未完全消失, 进入僵尸态.
## 如何杀死僵尸进程
僵尸进程已经 "死了", 所以没有办法 "杀死" 它们. 如//3cantkill//.
!![3cantkill,僵尸进程无法杀死]
杀死它们的父进程, 使它们成为孤儿进程进而被 `init`(systemd) 接纳并清理, 可以使它们消失. 如//3cleanzomb//.
!![3cleanzomb,杀死父进程进而清理僵尸进程]
## 改进 `test3-1` 使其不留僵尸子进程
一个最简单的方法是用 `signal(SIGCHLD, SIG_IGN)` 通知内核父进程忽略子进程退出的 `SIGCHLD`
信号, 从而使系统自动释放子进程的进程描述符.
编辑 `test3-2.c` 的内容:
~~~~~~~~~~~~~C
~~~~~~~~~~~~~
编译运行它, 当只剩下 `main` 输出时, 在另一终端查询进程信息, 发现没有僵尸进程留下了:
!![3pids2,运行 `test3-2`, 只剩 `main` 输出]
!![3nodefunct,只有主进程存在]