揭秘僵尸进程:父进程为何必须等待子进程

发布时间:2026/10/5 9:06:12

揭秘僵尸进程:父进程为何必须等待子进程 进程等待进程等待必要性为什么之前讲过子进程退出父进程如果不管不顾就会造成僵尸进程的问题进而造成内存泄漏。另外进程一旦变成僵尸进程进程停止运行不被CPU调度进程只剩下PID和退出码就难以杀死kill -9都没办法因为谁也没用办法去杀死一个已经死去的进程kill -9是信号但是僵尸进程无法被CPU调用就无法接收信号就难以被清理最后父进程派给子进程的任务完成的如何我们需要知道父进程通过进程等待的方式回收子进程资源子进程进程资源 内核级资源、最重要获取子进程退出消息(可选)。进程死亡 进程终止 进程资源回收子进程终止父进程不处理就是不做资源回收子进程就成为僵尸进程了 这也是为什么要进程等待僵尸进程的危害会但用PID资源导致新进程无法创建进程等待的方法是什么父进程创建出子进程后父进程必须要想办法通过上面的接口来等待子进程所以父进程通过使用wait和waitpid的操作就是进程等待通过代码来验证一个是否会产生僵尸进程确实产生了僵尸进程通过进程等待的方式来回收子进程解决僵尸进程这里通过wait来验证我们先来讲讲waitwait函数参数是输出型参数给wait函数传输一个整型变量地址用来存储子进程退出码函数调用成功后父进程就可以通过这个wstatus指针来获取退出码wait()wait是等待那个进程呢是等待任意一个退出的子进程父进程创建一个子进程就等待这一个子进程若创建10个子进程wait就会阻塞掉直到这10个子进程中任意一个退出了就返回那个退出的子进程解决子进程僵尸问题wait函数返回值是回收成功子进程的PID即目标僵尸进程的PID若失败就返回-1如果等待子进程子进程没有退出父进程会阻塞在wait调用处(与scanf同理)可以看到wait回收僵尸进程成功waitpid()这里wait 是简单版等待如果想要获得更多的子进程信息可以使用waitpidpid_t waitpid(pid_t pid,int *wstatus, int options);等待成功返回值是子进程PIDwstatus为输出型参数父进程可以通过这个指针获得子进程的退出码optione是阻塞控制pid为父进程需要等待的子进程pid大于0表示传进来的PID是谁父进程就等这个子进程等于-1 就等价于wait等待任意一个退出的子进程0和小于-1暂时不了解所以上面的案例使用waitpid也可以并且上图这样写id可以写-1-1就和wait一样了效果一致wait/waitpid失败的原因1、进程本身没有子进程2、waitpid传pid参数传错了通过上图案例来看看等待失败的情况我们手动的将子进程的PID1对rid返回值小于0的情况做判断int *wstatus参数这个参数为输出型参数我们知道函数返回数据有两种方式return返回还有一种就是指针传参返回传入指针在函数内部对指针指向地址存储同样达到了return这样向外输出的操作父进程要通过waitpid来获取子进程的退出信息如何评估这个退出信息呢这就是为什么我们要先讲解进程退出了根据进程退出码即main函数返回值来评估我们来试试我们子进程退出码为1wstatus获取的子进程退出信息为什么退出码不为1呢这就说明我们对wstatus的认知有问题要根据实际情况来考虑所以wstatus不只有退出码这个wstatus为整型但是实际上是被划分成多个区域可以当成一个位图来看整型为32B其中高16x不考虑低16x中的15x~8x表示退出码后8位中其中6x~0x表示退出信号7x为core dump高位的core dump和终止信号我们现在不谈要到信号才理解core dump占一个比特位低7个比特位表示的是进程退出时的退出信号默认情况下退出情况为程序运行完毕时core dump和终止信号这八个比特位都为0我们案例的情况这个整型的二进制数位100000000转化为十进制数为256那我们要如何获取我们子进程的退出码呢将这个整型变量右移8位在提取前8位数据所以我们对wstatus做操作(wstatus8)0xFF(0xFF为常数有4个字节二进制数前8位为1后面24位为0),先右移在按位与从而获得所以我们bash通过echo $?获取退出码也是用这个格式来转换的(wstatus8)0xFF面对异常我们就不能演示了因为还没有讲到信号但是我们用过一个信号那就第九个信号其实这些信号都是宏定义进程异常终止就在比特位低7为保存异常时对应的信号编号如果没有异常低7位就全为0因为我们发现信号没有0信号所以就认为终止时候没有收到信号一旦低7位比特位!0就代表着异常退出退出码无意义因为程序没有运行完我们来试试获取子进程运行的退出信号通过使用0x7F常量与wstatus来按位与0x7F二进制数为0111 1111所以按位与可以获取前7个比特位数据我们来制造异常来看看情况如何通过让子进程死循环父进程在等待子进程子进程死循环那就是父进程死循所以我们在其他bash端向子进程发出信号kill -9 PID来终止进程此时我们可以看到waitpid获得的退出信息退出信号为9而退出码为0无意义或者是直接让子进程对0地址赋值出现异常子进程接受异常退出父进程接收退出信息对wstatus分析可以获取退出信号为11子问题理解wait、wstatus位操作宏、option理解wait接口进程具有独立性父进程不能直接拿到子进程的退出信息退出码、退出信号通过全局变量来获取没意义写时拷贝后内存重新分配所以需要wait系统调用接口来实现那这些系统调用是从子进程什么地方拿到退出信息的呢我们要了解系统调用在哪里拿的退出信息就要知道退出信息存在哪里子进程退出进程需要进入僵尸状态虚地址空间和页表可以释放掉但是PCB还要保留所以子进程僵尸只剩下PCB退出信息只能存储在PCB内在PCB内可以预测到int exit_code;int exit_signal;这样的整型数据当子进程退出时OS就会把子进程main的返回值保存到子进程PCB退出信号默认为0若有信号就存储进去父进程通过调用waitpid系统调用通过调用这个接口找到子进程PCB找到子进程的退出信息并通过位操作我们是按位与这里就逆操作按位或赋值给父进程的wstatus父进程从而获取子进程的退出信息这就是waitpid系统调用的实现父进程向系统申请获取子进程退出信息系统就向子进程查找退出信息并将退出信息交给父进程这也解释了之前的系统调用getpid()的调用原理了所以这就是需要僵尸进程的原因wstatus位操作的宏我们知道wstatus整型真正的使用方式和位图类似分为多个区域操作退出码和退出信号的区域分别在8x~15x和0x~6x,我们要获得对应的退出信息要自己做位操作但是OS不想让你操作OS内部有想要的位操作方法我们来了解了解WIFEXITED(wstatus): 判断子进程退出信号是否异常如果异常需要输出信号可以使用wstatus0x7F来获取WEXITSTATUS(wstatus)WIFEXITED(wstatus)为非零提取子进程退出码所以WIFEXITED通常用于成功等待后判断子进程是否异常就像上图等待成功信号无异常就输出rid和退出码信号异常就输出信号异常其实对于具体某个异常信号的获取没有移动要求只有专门调试的时候在需要知道optionwaitpid()内部还有一个参数我们没有提及过那就是int option!这个参数可以设置一些选项默认为0时代表默认阻塞等待其他的选项很多都不用了但是我们要来谈谈选项WNOHANGreturn immediately if no child has exited如果子进程没有退出我们就立即返回即非阻塞调用非阻塞调用我们应该是第一次认识WwaitNO:不要HANG夯住当计算机卡死了做任何操作没有反应就可以说这个计算机被夯住了可以说子进程阻塞了,则WNOHANG就是不夯住就是不阻塞用例子来理解要期末考试了小张没有上课舍友小李是学霸有完整的笔记小张就打电话给小李想找小李给他补课小李说没问题但是要等他一会小张就说没问题然后挂了电话每个一会小张等不及了又打电话给小李小李还没有好小张又挂了小张就这也打了多次电话直到小李下来其中打电话是函数调用小李是OS小张是用户小张打电话就是一次调用打一次电话挂了知道小李没结束是非阻塞查了一次状态是没结束小李什么时候结束也不清楚只能打多次电话 这就是非阻塞轮询访问子进程发现未结束就立即函数返回多次查询后面小张发现又有一科课程要考试了也没上又打电话找小李这次小李同样要等一会小张说可以等你然后说我不挂电话了等你出门了我再挂电话这里小张不挂电话等待直到小李把操作做完才挂电话即用户waitpid访问子进程一直等待子进程结束才返回这就是阻塞调用scanfcin轮询是计算机中的术语所以的轮询在计算机中都是通过循环实现的在循环调用waitpid时每次循环都判断waitpid的返回pidpid 0等待结束pid 0调用结束但是子进程没有退出pid 0等待失败我们再回到非阻塞轮询的例子挂电话期间小张也可以做一些自己的事前看看C语言书、刷手机、发呆等等反正小张可以做自己的事情过来一会再向小李打电话非阻塞调用可以让等待方做做自己的事情再通过一个例子来展示非阻塞调用父进程可以周期性的做自己的事情上面这个例子就展示了在非阻塞调度期间父进程做自己的任务周期性的做自己的任务提高了父进程的效率解放生产力而我们在bash调用sleepsleep也是进程我们发现bash调用sleep后不能调用其他命令这是因为bash在阻塞调用sleepbash等待sleep子进程调用完才继续运行
延伸阅读

更多相关文章

2026/10/3 4:35:00

2026年8月GEO洞察检测工具排行榜

2026年8月GEO洞察检测工具排行榜 一、为什么"GEO洞察检测"需要一份严肃的排行榜 2026年,Gartner关于"约25%传统搜索行为被AI问答取代"的预测正在应验。当用户开始习惯在豆包、DeepSeek、Kimi、元宝里直接问"哪个品牌好"时&#xff0c…

2026/10/2 20:50:25

Java实现电商推荐系统:SpringBoot+协同过滤实战

1. 项目概述:唯品会推荐系统的技术架构与核心价值 作为一名长期从事电商系统开发的工程师,我参与过多个推荐系统的设计与实现。今天要分享的是基于Java技术栈的唯品会风格推荐系统实现方案。这个系统采用了SpringBootSSM的主流框架组合,核心难…

2026/10/5 9:02:31

MATLAB驱动SAP2000 API:从对象模型到批处理参数化建模全攻略

1. 为什么我最终选择“MATLAB驱动SAP2000 API”这条路先说背景。我之前在做一个高层框筒结构的参数化对比分析,要一次性算几十个模型:层高变化、柱截面变化、地震工况组合变化。如果靠手动在SAP2000里建模,一个模型至少半个小时,改…

2026/10/5 9:02:31

无人机河道垃圾识别实战:YOLOv11+spacedrone落地指南

1. 项目概述:为什么河道垃圾识别必须用无人机图像识别组合拳?我第一次在长江支流做环保巡查时,站在岸边用望远镜扫了整整两小时,只发现3处漂浮垃圾——而当天无人机飞完12公里河段,自动标记出47个疑似点,人…

2026/10/5 9:02:31

WorkBuddy实战指南:AI Agent办公自动化与MCP协议开发

1. 这不是“又一个AI工具”,而是你办公桌边新来的搭档WorkBuddy这个词,最近三个月我每天打开电脑第一件事就是点开它。不是因为上头,而是因为它真正在帮我扛活儿——上周五下午四点,市场部临时要一份竞品功能对比PPT,我…

2026/10/5 9:02:31

Embedding 向量嵌入:语义空间、相似度与模型选择

一句话怎样变成一串数字 计算机很容易比较数字,却不能直接理解“如何启动服务”和“服务的启动步骤”表达了相近含义。Embedding 模型解决的正是这个问题:它把文本、图片或音频映射成一组稠密向量,让语义关系能够通过数学距离来比较。 “如…

2026/10/5 8:57:31

行人实例分割数据集实战:YOLOv8-seg训练与Re-ID裁剪

简介:行人实例分割数据集面向智能安防、自动驾驶感知、服务机器人交互及计算机视觉研究等场景,为需要训练高精度行人识别与轮廓分割模型的开发者提供可直接使用的工业级数据。资源包共2000个文件,以1226个txt标注文件、772张jpg图像为主&…

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/4 0:01:02

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/4 1:01:05

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑