最近在做一个项目,大概思路是
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