铅笔

在你的害怕中坚持的越多,你就会越自信
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

父进程号为1的特殊的僵尸进程

Posted on 2020-03-27 15:20  黑色の铅笔  阅读(6873)  评论(0编辑  收藏  举报

最近在做一个项目,大概思路是

1.在一个进程中创建n个线程

2.每个线程中再启动某一进程,当该进程执行完毕后,再次启动该进程

难点在于对于需启动的进程的监测:

实现思路是:检测/proc/pid/stat目录文件,只有当进程存在时才能够打开该文件,文件中对进城的一些信息进行了基础描述

遇到的问题为:长时间循环启动进程总会出现进程“不运行”的情况,排查了很久发现是“僵尸进程“导致。此时/proc/pid/stat中的进程的状态描述为“Z” 即表示僵尸进程,如下 

 

 解决方案:对于一般的父进程创建后可以直接使用wait或者waitpid进行子进程的回收,可是我使用的创建进程模式是分离式,即创建后父进程号为1(init进程),对于这种情况一方面是找到产生这种僵尸进程的原因进而避免,另外一个方面如果实在避免不了,那就需要进行判断该进程到底何时成为僵尸进程,然后再根据自己的业务逻辑进行处理,比如说杀死该进程然后重新创建(一般这种僵尸进程只能将其父进程杀死后才能彻底将其清除)也可以直接忽略了该进程重新创建一个新的进程(由于这个时候的僵尸进程由init进程直接处理,所以不用担心其不会回收)

在一篇博客中找到了产生这种进程的解释

====================== 以下是原文 ======================
首先是 父进程为1号进程的进程 会不会成为僵尸进程??

---------------------------------------普通进程------------------------------------------

普通进程,父进程不主动去回收子进程的资源。
一个子进程在其父进程还没有调用wait()或waitpid()的情况下退出。这个子进程就是僵尸进程。产生僵尸进程的原因:
1、子进程结束后向父进程发出SIGCHLD信号,父进程默认忽略了它;
2、父进程没有调用wait()或waitpid()函数来等待子进程的结束;

处理办法:把父进程杀掉,僵尸进程会变成孤儿进程,然后过继给1号进程,而1号进程会扫描名下子进程,把 Z 状态进程回收;

这时候僵尸进程已经退出了,只保留了task_struct结构体,所以发信号(-9等信号)去处理僵尸进程是无效的;

-----------------------------------ppid=1的进程-------------------------------

通过对普通僵尸进程的分析,这样看起来好像 父进程为1号进程的进程 不会成为僵尸进程了,因为1号进程都会时刻扫描其子进程的状态。

发现是 僵尸进程就会马上去释放它的资源;

但是,父进程为1号进程的进程 其实也是有可能成为僵尸进程的。下面说几种情况:

1、进程还在被其它进程使用,退出;

2、进程的子线程还在执行任务,但主线程已经死掉了(可能主线程已经被杀了,systemd停止服务时会发SIGTERM信号);

3、进程阻塞在某一IO请求上,这时控制权已交到内核手上,这时如果子进程被KILL掉, 那么就成为父进程ID为1的僵尸进程,这个进程不会退出,会一直阻塞直到IO请求被满足;

那当出现父进程为1号进程的僵尸进程时,需要分析时,可以考虑上面几种情况;

1、查看下当前这个僵尸进程是否被其他进程使用,比如:被跟踪,调试之类的;

2、用ps -T -p 查看下这个僵尸进程的主线程是否退出;

3、用strace 跟踪下这个僵尸进程看看是否有io在等待,或者查看下载僵尸之前是否有io类的操作发生;
————————————————

 


原文链接:https://blog.csdn.net/KgdYsg/article/details/89503457