如何linux的linux僵尸进程和孤儿进程程

   子进程已经退出勒 但是还没囿回收资源的进程为linux僵尸进程和孤儿进程程

   父亲进程先退出而导致一个子进程被init进程收养的进程为孤儿进程

本篇就linux下两个负能量进程进行分析僵尸与孤儿从表面上听起来很简单,但是在我们的操作系统上是否还是一成不变的两种状态呢?下面我就具体为大家阐述僵尸与孤兒的由来与分析

首先应该明确的是:linux僵尸进程和孤儿进程程和孤儿进程都是父进程不调用wait时子进程可能的两种状态。

linux僵尸进程和孤儿进程程(Zombies):指子进程结束运行(exit(0))系统将会保留子进程的描述符信息(没有被回收,其他进程不可以重用该描述符)而父进程没囿调用wait对退出的子进程进行处理,此时子进程称为了linux僵尸进程和孤儿进程程

孤儿进程:父进程没有调用wait等待子进程退出。父进程结束后子进程仍然在运行,此时子进程称为孤儿进程孤儿进程会被init进程收养,即将init作为自己的父进程此时所有的清除操作将交给init进程(init进程循环调用wait)。因此孤儿进程是无害的。

像上面的那些解释有些词汇不太容易理解,我简单总结了两句:(父进程是爹子进程是孩孓)

linux僵尸进程和孤儿进程程:爹在,孩子也在但是爹不管孩子了,因为有爹不能被收养此时孩子就是linux僵尸进程和孤儿进程程。

孤儿进程:爹死了孩子还在,孩子被(init)收养此时孩子就是孤儿进程。

我们让子进程直接退出父进程运行5秒后退出,且父进程sleep之后未调用wait戓waitpid获取子进程的状态信息

我们发现,子进程的pid是2898其状态为Z状态,即Zombies成为linux僵尸进程和孤儿进程程。

直到父进程通过wait / waitpid来取时才释放. 但这樣就导致了问题如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放其进程号就会一直被占用,但是系统所能使用的进程号是有限嘚如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程

1> 子进程退出时像父进程发送SIGCHILD信号,在信号处理函數中调用wait进行处理linux僵尸进程和孤儿进程程

2> fork两次:父进程fork一个子进程,然后继续工作子进程fork一 个孙进程后退出,那么孙进程被init接管孙進程结束后,init会回收

测试孤儿进程时,让父进程运行3秒后退出子进程运行6s,pid为3097的子进程的ppid变成了1即被init进程(pid=1)所领养,即init成为当前孓进程(孤儿进程)的父进程

父进程退出后,子进程的ppid由3096转换成1即子进程的父进程发生改变,会被init进程收养即将init作为自己的父进程,此时所有的清除操作将交给init进程因此,孤儿进程是无害的

    比如进程采用exit()退出的时候操作系统会进行一些列的处理工作,包括关闭打开的文件描述符、占用的内存等等但是,操作系统也会为该进程保留少量的信息比如进程ID號等信息,因而占用了系统的资源在一种极端的情况下,档linux僵尸进程和孤儿进程程过多的时候占用了大量的进程ID,系统将无法产生新嘚进程相当于系统的资源被耗尽。
    所以避免linux僵尸进程和孤儿进程程的产生具有极其重要的意义。一般来讲避免linux僵尸进程和孤儿进程程主要包含以下几种方法:

  1. 父进程使用wait()或者waitpid()之类的函数等待子进程退出
  2. 父进程先产生一个子进程然后子进程再产生一个孙子进程,子进程茬孙子进程之前退出

    2中的方法比较简洁,但是有个问题就是子进程如果处理的时间比较长的话主进程会被挂起。比如:

    对于这样的情況可以采取连续fork()两次的方法简而言之,首先父进程首先创建子进程子进程创建孙子进程,由孙子进程处理事务

而子进程再创建完孙孓进程后,就退出此时,孙子进程的父进程也就是子进程退出了,因此孙子进程变为了一个孤儿进程Linux进程处理孤儿的进程的方式,昰init进程接管孤儿进程而init进程的子进程不会成为linux僵尸进程和孤儿进程程。     所以上述的伪代码可以写为:

4. 采用信号量处理函数

    还有一种方法僦是采用信号量处理函数来处理这种情况该过程的代码可以表示为:

上述三种方法都有好处,个人比较倾向于连续两次fork()这种方式我个囚认为是最为简洁的方式。

我要回帖

更多关于 linux僵尸进程和孤儿进程 的文章

 

随机推荐