尧图精选

孤儿进程和僵尸进程分别是什么?怎么形成的?

🕒 发布时间:2026/9/2 6:06:41 📁 来源:尧图网络
1. 引言在 Linux 系统中进程管理是操作系统核心功能之一。孤儿进程和僵尸进程是进程生命周期中两种常见且容易混淆的状态。理解它们的形成原因、区别以及处理方法对于系统运维和后台服务开发都非常重要。2. 进程的基本概念在深入讨论之前先回顾几个关键概念父进程创建其他进程的进程通常通过fork()系统调用产生子进程。子进程由父进程创建的新进程继承父进程的代码、数据和资源。进程状态进程在生命周期中会经历运行、就绪、阻塞、停止等多种状态。进程表内核维护的数据结构记录每个进程的 PID、状态、退出码等信息。3. 孤儿进程3.1 什么是孤儿进程孤儿进程是指父进程已经退出但子进程仍在运行的进程。此时子进程的父进程变为 init 进程PID 为 1由 init 进程负责回收。3.2 形成过程孤儿进程的形成过程如下父进程通过fork()创建子进程。父进程在子进程尚未结束时提前退出例如正常结束、崩溃或被杀死。内核将子进程的父进程重新设置为 init 进程。init 进程接管该子进程并在其退出时负责回收资源。3.3 示例代码#include stdio.h #include unistd.h #include stdlib.h int main() { pid_t pid fork(); if (pid 0) { perror(fork); exit(1); } if (pid 0) { // 子进程 printf(子进程 PID%d, 父进程 PID%d\n, getpid(), getppid()); sleep(5); printf(子进程醒来父进程 PID%d\n, getppid()); } else { // 父进程立即退出 printf(父进程 PID%d 退出\n, getpid()); exit(0); } return 0; }运行后可以看到子进程醒来时其父进程 PID 已经变为 1init 进程。3.4 孤儿进程的影响孤儿进程本身不会造成资源泄漏因为 init 进程会负责回收。但在容器或嵌入式环境中如果 init 进程被替换或缺失孤儿进程可能无法被正确回收导致资源占用。4. 僵尸进程4.1 什么是僵尸进程僵尸进程是指子进程已经终止但其退出状态尚未被父进程读取的进程。此时子进程已经释放了大部分资源但在进程表中仍保留一条记录等待父进程调用wait()或waitpid()获取其退出状态。4.2 形成过程僵尸进程的形成过程如下父进程通过fork()创建子进程。子进程运行结束调用exit()退出。内核保留子进程的退出状态和进程表项等待父进程读取。如果父进程没有调用wait()或waitpid()子进程就变成僵尸进程。4.3 示例代码#include stdio.h #include unistd.h #include stdlib.h int main() { pid_t pid fork(); if (pid 0) { perror(fork); exit(1); } if (pid 0) { // 子进程立即退出 printf(子进程 PID%d 退出\n, getpid()); exit(0); } else { // 父进程不调用 wait睡眠观察 printf(父进程 PID%d 睡眠不回收子进程\n, getpid()); sleep(10); } return 0; }运行期间执行ps -ef | grep defunct可以看到状态为 Z 的僵尸进程。4.4 僵尸进程的影响僵尸进程无法被杀死kill 无效因为其已经终止。如果父进程长期不回收僵尸进程会持续占用进程表项当进程表满时系统将无法创建新进程。5. 孤儿进程与僵尸进程的区别对比项孤儿进程僵尸进程进程状态仍在运行已终止等待回收父进程状态父进程已退出父进程仍在运行资源占用占用正常资源仅占用进程表项能否被 kill可以不能回收方式由 init 进程接管由父进程调用 wait()危害程度一般较小可能耗尽进程表6. 如何避免僵尸进程6.1 父进程调用 wait()父进程在子进程退出后调用wait()或waitpid()及时回收子进程的退出状态。6.2 使用信号处理父进程注册SIGCHLD信号处理函数在子进程退出时自动回收。#include stdio.h #include unistd.h #include stdlib.h #include signal.h #include sys/wait.h void handler(int sig) { while (waitpid(-1, NULL, WNOHANG) 0); } int main() { signal(SIGCHLD, handler); pid_t pid fork(); if (pid 0) { printf(子进程退出\n); exit(0); } sleep(5); return 0; }6.3 双重 fork父进程 fork 一个子进程子进程再 fork 孙进程后立即退出孙进程由 init 进程接管从而避免僵尸进程。7. 总结孤儿进程和僵尸进程是进程生命周期中的两种特殊状态。孤儿进程是父进程先退出子进程被 init 接管僵尸进程是子进程先退出父进程未回收。理解它们的形成机制和区别有助于编写健壮的后台服务避免进程表耗尽等问题。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →