什么是Linux僵尸进程?怎么产生的?怎么避免?

僵尸进程是指它的父进程已经退出(父进程没有等待(调用wait/waitpid)它) , 而该进程dead之后没有进程接受 , 就成为僵尸进程 , 也就是(zombie)进程 。

什么是Linux僵尸进程?怎么产生的?怎么避免?

文章插图
 
 
一个进程在调用了exit命令之后结束了自己的生命时候 , 你以为是真的被彻底销毁了吗?其实不然 , 它只是变成了我们称之为“僵尸进程”状态 。在用户态程序调用系统调用exit时 , 也仅仅限于将一个正常的进程变成了一个僵尸进程 , 并没有完全的销毁 。看下图所示:
 
什么是Linux僵尸进程?怎么产生的?怎么避免?

文章插图
 
 
在linux中 , 进程的状态有5种 , 其中僵尸进程状态是一种比较奇葩的存在方式 , 它放弃了几乎所有的内存地址空间 , 也没有任何的可执行的代码 , 也不可能被调度器再次调度 , 它仅仅是在进程列表中保留一个位置 , 在这个位置中记载了该进程的状态 。而它也只是静静的等待着其他进程(父进程后者init进程)为他收尸 。
假如它的父进程没有安装SIGCHLD信号处理函数来处理子进程(也即使wait或者waitpid等待儿子结束) , 又没有显示忽略该信号 , 那子进程就会一直保持僵尸状态 。只有在父进程结束之后 , 才由init进程接管子进程 , 为他收尸(好凄惨啊) , 这个时候才能说子进程才真正的消失在Linux内核中 。
又假如父进程是个无限循环的进程 , 那么子进程就会一直保持僵尸状态 。这就能解释为什么系统运行久了 , 会出现大量的僵尸状态的进程 。出现僵尸状态进程的数量少 , 是没有任何问题的 , 一旦出现巨量情况 , 就会导致PID用完 , 而给新的进程分配PID , 当然也就会创建新进程失败 。
为什么要有僵尸状态呢?主要是因为父进程可能要取得子进程的退出状态等信息 。僵尸状态是每一个进程必须要经过的过程(除init进程之外) 。
 
那怎么避免呢?当前能给出四种方案 , 分别是:
  1. 父进程通过wait或waitpid函数等待子进程结束 , 这样有个问题 , 就是会导致父进程挂起 。
  2. 如果父进程很忙 , 可以采用异步的方式 , 注册SIGCHLD信号处理函数 , 在处理函数中wait回收子进程 。
  3. 如果父进程对子进程生死不感兴趣 , 也可以通过signal(SIGCHLD,SIG_IGN)告知内核 , 忽视掉该信号 。当然子进程结束后 , 内核会帮助回收 。
  4. 还可以用一些技巧 , 比如fork两次 。子进程退出 , 孙进程就由init进程接管回收了 。这个方法的代码网络上多如牛毛 。自信百度查看 。
?
如何查看僵尸进程呢?【什么是Linux僵尸进程?怎么产生的?怎么避免?】在Linux中 , 可以使用ps命令 , ps 命令就是最根本相应情况下也是相当强大地进程查看命令.运用该命令可以确定有哪些进程正在运行和运行地状态、 进程 是否结束、进程有没有僵死、哪些进程占用了过多地资源等等.总之大部分信息均为可以通过执行该命令得到地.
标记“Z”的进程就是僵尸进程了 。
ps -ef可以用ps的-l选项,得到更详细的进程信息.
F(Flag):一系列数字的和 , 表示进程的当前状态 。这些数字的含义为:
00:若单独显示 , 表示此进程已被终止 。01:进程是核心进程的一部分 , 常驻于系统主存 。如:sched、 vhand 、bdflush 等 。02:Parent is tracing process.04:Tracing parent’s signal has stopped the process; the parent is waiting ( ptrace(S)).10:进程在优先级低于或等于25时 , 进入休眠状态 , 而且不能用信号唤醒 , 例如在等待一个inode被创建时20:进程被装入主存(primary memory)40:进程被锁在主存 , 在事务完成前不能被置换S(state of the process )
O:进程正在处理器运行S:休眠状态(sleeping)R:等待运行(runable)I:空闲状态(idle)Z:僵尸状态(zombie)T:跟踪状态(Traced)B:进程正在等待更多的内存页C:cpu利用率的估算值(cpu usage)另外使用top命令查看时有一栏为S,如果状态为Z说明它就是僵尸进程 。


推荐阅读