僵尸进程详解

僵尸进程详解僵尸进程简介 僵尸 进程是什么 通常情况下 造成僵尸进程的成因是因为该进程本应该已经执行完毕 但是该进程的父进程却无法完整的将该进程结束掉 而造成该进程一直存在于内存中 那么如何查看一个进程是否为僵尸进程呢 ps 将某个时间点的进程运行状态选取下来 psaux 查看系统所有的进程数据 A 所有的进程均显示出来 a 不与 terminal 有关的所有进程 u 有效用户相关的进程 x 通常

僵尸进程简介

“僵尸”进程是什么?通常情况下,造成僵尸进程的成因是因为该进程本应该已经执行完毕,但是该进程的父进程却无法完整的将该进程结束掉,而造成该进程一直存在于内存中。

那么如何查看一个进程是否为僵尸进程呢?

ps:将某个时间点的进程运行状态选取下来 ps aux //查看系统所有的进程数据 -A:所有的进程均显示出来 -a:不与terminal有关的所有进程 -u:有效用户相关的进程 -x:通常与a一起使用,可以列出较完整的信息 -l:较长、较详细地将该PID的信息列出

如上图

也可以通过top指令来查看是否存在僵尸进程

top:动态查看进程的变化 top:参数 -d:后面接秒数,表示显示整个进程界面更新的秒数,如top -d 5 -b:以批次的方式执行top -n:与-b搭配,意思是需要几次top输出的结果 -p:指定某个特定的PID进行检测

光标处即目前的僵尸进程数量。


举例

这是一个维持30秒的僵尸进程

#include 
     #include 
     int main(int argc,char argv[]) { int id = fork(); if(id>0) { printf("Parent is sleeping\n"); sleep(30); } if(id == 0) printf("Child process is done\n"); exit(EXIT_SUCCESS); } 

通俗一点,僵尸进程就是指子进程先于父进程挂掉 但是父进程并没有正确回收子进程的资源而已。


进程的管理

当你获知它是一个僵尸进程后,那么你该如何干掉它呢,那么首先就得了解一下进程的管理。

程序之间的相互管理,是通过给予一个信号来进行管理的

这里写图片描述


总的来说,当系统不稳定时,或者代码不够完善,亦或是用户操作不当都可能产生僵尸进程,而僵尸进程是1个早已死亡的进程,但在进程表(processs table)中仍占了1个位置(slot)。由于进程表的容量是有限的,所以就占用了内存资源,影响系统性能。


补充:

如何防止僵尸进程的产生

如上所述,当子进程先行退出,且父进程不对其做回收的话,会产生僵尸进程,我们可以通过的进程等待,来让父进程等待子进程退出然后进行回收。

具体的进程等待这里就不赘述了。可以参考进程控制中的进程等待部分。

这里主要是为了提一下后续学到了信号部分的知识,当子进程退出时操作系统会发送SIGCHLD信号,而该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程就可以处理自己的事情,而不必关心子进程的退出,在父进程的处理函数中调用wait清理子进程即可。

看如下代码:

#include 
        #include 
        #include 
        #include 
        #include 
        #include 
        //自定义SIGCHLD信号的处理函数,对子进程进程wait void Myhandler(sigset_t signal) { printf("wait\n"); wait(NULL); } int main() { //当收到SIGCHLD信号时,执行自定义的处理函数 signal(SIGCHLD,Myhandler); pid_t id = fork(); if(id > 0){ //father while(1){ printf("father doing some thing!\n"); sleep(1); } }else if(id == 0){ //child sleep(3); exit(1); }else{ perror("fork"); return 1; } return 0; } 
void Myhandler(sigset_t signal) { printf("wait\n"); wait(NULL); } int main() { signal(SIGCHLD,Myhandler); pid_t cid; int i = 0; for(;i < 20;++i) { cid = fork(); if(cid == 0) exit(0); } if(cid > 0) { while(1) { printf("father doing some thing!\n"); sleep(1); } } else if(cid == 0) { sleep(3); } return 0; }

这里写图片描述
可以看到,只wait了15次,这样意味着产生了5个僵尸进程,来查看一下系统中是否真的出现了5个僵尸进程。
这里写图片描述
解释下为什么会出现僵尸进程,因为操作系统在接受到一个信号时,在执行处理函数时,就会屏蔽该信号,所以当有多个子进程同时退出发送信号时,操作系统就收到一个信号,所以就造成僵尸进程的出现。






基于这个问题,可以采用两种发生来解决。

一:一次处理函数wait多个子进程

void Myhandler(sigset_t signal) { pid_t id; while((id = waitpid(-1,NULL,WNOHANG) > 0)){ printf("child wait success:%d\n",id); } printf("child is quit!\n"); } int main() { signal(SIGCHLD,Myhandler); pid_t cid; int i = 0; for(;i < 20;++i) { cid = fork(); if(cid == 0) exit(0); } if(cid > 0) { while(1) { printf("father doing some thing!\n"); sleep(1); } } else if(cid == 0) { sleep(3); } return 0; }

这里写图片描述
这里写图片描述
由于篇幅问题,有一点没截上,可以看到子进程全部被回收了,系统中并没有产生僵尸进程。




二:使用sigaction函数

int main() { struct sigaction new,old; new.sa_handler = SIG_IGN; sigemptyset(&new.sa_mask); new.sa_flags = 0; sigaction(SIGCHLD,&new,&old); pid_t cid; int i = 0; for(;i < 20;++i) { cid = fork(); if(cid == 0) exit(0); } if(cid > 0) { while(1) { printf("father doing some thing!\n"); sleep(1); } } else if(cid == 0) { sleep(3); } sigaction(SIGCHLD,&old,NULL); return 0; }

就先补充到这了,后续有新的理解,会继续更新。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205533.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午5:48
下一篇 2026年3月19日 下午5:48


相关推荐

  • win10应用商店错误代码0x8000FFFF_错误代码0xc000007b

    win10应用商店错误代码0x8000FFFF_错误代码0xc000007b控制面板内打开网络和Internet Internet选项 连接 设置 自动检测设置

    2025年11月19日
    7
  • latex 公式如何换行

    latex 公式如何换行1、如图所示,我们先写个长公式。2、可以看到,公式没有自动换行,而是跨过了一栏。3、如图所示,在公式上下两端加上split。同时使用\\指明换行的位置。4、如图所示,公式实现了自动换行。5、大家选择换行的位置也很重要。如图所示,选择该处换行6、得到的效果就非常糟糕。承接Matlab、Python和C++的编程,机器学习、计算机视觉的理论实现及辅导,本科和硕士的均可,咸鱼交易,专业回答请走知乎,详谈请联系QQ号757160542,非诚勿扰。…

    2022年5月4日
    320
  • 无刷直流电动机驱动控制系统_直流无刷电机驱动电路

    无刷直流电动机驱动控制系统_直流无刷电机驱动电路无刷直流电动机利用电子开关线路和位置传感器来代替有刷直流电机电刷和换向器,使其同时具有直流电动机和交流电动机的优良特性。无刷直流电机(驱动系统)主要由电动机本体、位置传感器、电子开关线路三部分组成。

    2022年10月21日
    6
  • SIP协议简介

    SIP协议简介这里写自定义目录标题欢迎使用 Markdown 编辑器新的改变功能快捷键合理的创建标题 有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中 居左 居右 SmartyPants 创建一个自定义列表如何创建一个注脚注释也是必不可少的 KaTeX 数学公式新的甘特图功能 丰富你的文章 UML 图表 FLowchart 流程图导出与导入导出导入欢迎使用 Markdown 编辑器你好 这是你第一次使用 Markdown 编辑器所展示的欢迎页 如果你想学习如何使用 Mar

    2026年3月17日
    3
  • kaptcha验证码[通俗易懂]

    kaptcha验证码[通俗易懂]kaptcha是一个非常实用的验证码生成工具。有了它,你可以生成各种样式的验证码,因为它是可配置的。kaptcha工作的原理是调用com.google.code.kaptcha.servlet.KaptchaServlet,生成一个图片。同时将生成的验证码字符串放到HttpSession中。使用kaptcha可以方便的配置: 验证码的字体验证码字体的大小验证码字体的字

    2022年6月18日
    30
  • 我如何为 OpenClaw 构建了一个自动学习技能

    我如何为 OpenClaw 构建了一个自动学习技能

    2026年3月13日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号