孤儿进程和僵尸进程个人总结

1.孤儿进程和僵尸进程

Unix/Linux中有孤儿进程和僵尸进程的概念如下:

  • 孤儿进程:如果父进程退出而它的一个或多个子进程还在运行,那么这些子进程就被称为孤儿进程。孤儿进程最终将被 init 进程所收养并由 init 进程完成对它们的状态收集工作。
  • 僵尸进程:一个进程使用 fork() 创建子进程,如果子进程退出而父进程并没有调用 wait() 或者 waitpid() 获取子进程信息,那么子进程的描述符仍然保存在系统中。这种进程称为僵尸(zombie)进程,也译僵死进程。
  • 孤儿进程没有危害。僵尸进程有危害。僵尸进程占用资源不放,正常进程可能无法进行创建。
  • 解决僵尸进程只能找到那个产生大量僵死进程的父进程,只有杀死掉那个父进程 (通过 kill 发送 SIGTERM 或 SIGKILL) 杀死掉那个父进程之后,那些僵死进程就成了孤儿进程,孤儿进程会被 init 进程接管,init 会 wait()掉这些孤儿进程并且释放它们在系统中占用的资源这些僵死的孤儿进程就会死去。

2. 浮想联翩

孤儿进程和僵尸进程让我联想到JVM学到的内存泄漏和内存溢出。准确的说是僵尸进程和内存泄漏有一定的相似性。

  • 僵尸进程:虽然存在(进程描述符仍然保存在系统中),但属于占着茅坑不拉屎的玩意,还对系统有害导致正常的进程无法创建。
  • 内存泄漏:已分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等后果。
    两者都是因为某种原因导致进程所占用的资源无法正常被释放,最终导致一系列恶果。(o゜▽゜)o☆建立了一个桥梁联通JVM和Linux,又多了可以吹的点了~

3.Linux进程控制相关

3.1 基本概念

  unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。而Linux进程共同的先祖就是init进程。
  子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程到底什么时候结束。 unix/linux提供了这样的一个机制,保证只要父进程想知道子进程结束时的状态信息, 就可以得到。
  该机制是在每个进程退出的时候,内核释放该进程所有的资源,如占用的内存等, 但是仍然为其保留一定信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放,但这样也会就导致了一些问题。

3.2 存在的问题

  如果父进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但系统能使用的进程号是有限(如Linux0.11内核最多支持64个进程),如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程.这就是僵尸进程的危害。

  任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下task_struct(PCB)1的数据结构,等待父进程处理,这是linux进程转换约定流程,如下图,Linux进程最终从内核运行态用exit()方法终止,进入僵尸状态。
在这里插入图片描述
  如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。

  如果父进程在子进程结束之前退出,则子进程将由init接管(就是孤儿进程),init将会以父进程的身份对僵尸状态的子进程进行处理。

  当然严格说,僵死进程并不是问题的根源,产生出大量僵死进程的那个父进程才是罪魁祸首,找到该父进程过kill发送SIGTERM或者SIGKILL信号干掉后该父进程的子进程就变成了孤儿进程了由init进程接管。

3.3 僵尸进程解决的几个问题
  • 信号机制:向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理
  • fork方法调用两次:原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程。

图片出处见水印
在这里插入图片描述
STAT位常见状态字符,各个状态字符的解释,来自ps的man手册

D //无法中断的休眠状态(通常 IO 的进程);
R //正在运行可中在队列中可过行的;
S //处于休眠状态;
T //停止或被追踪;
W //进入内存交换 (从内核2.6开始无效);
X //死掉的进程 (基本很少见);
Z //僵尸进程;

有额外的字符对进程的状态做补充说明:
< //优先级高的进程
N //优先级较低的进程
L //有些页被锁进内存;
s //进程的领导者(在它之下有子进程);
l //多线程,克隆线程(使用 CLONE_THREAD, 类似 NPTL pthreads);
+ //位于后台的进程组;


在这里插入图片描述


  1. 参考《A Heavily Commented Linux Kernel Source Code》2.5节 ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值