请教个 Python subprocess 的 Popen 产生僵尸进程的问题。如题所示

2017-10-31 10:28:02 +08:00
 linhanqiu
例如这个例子:
import subprocess
b = subprocess.Popen("ping www.baidu.com",shell=True)
a = subprocess.Popen("ls -al",shell=True)

#b.wait()"一直在运行"
#a.wait()"执行马上就结束"
按照如上所示,有以下几种情况,
场景一
同时注释 a.wait(),b.wait()
并没有僵尸进程的出现

场景二
注释 a.wait()
出现执行命令 a 的僵尸进程的出现

场景三
注释 b.wait()
和场景一一样,没有出现僵尸进程

场景四
同时不注释
和场景二一样,出现执行 a 进程的僵尸进程出现

考虑到以上执行结果,以及僵死进程出现的原因和主进程相关的原因
我的想法如下:
Popen.wait()是说明主进程等待子进程结束才结束,现在普遍用这个方法来避免产生僵尸进程,
而我的情况不太一样,如果同时注释,说明 a 进程执行完,b 仍然在执行,主进程和 a 进程同时退出,不产生僵尸进程,而场景二,注释 a 的情况下,运行程序,a 进程执行完,b 进程仍然在执行,但是调用了 b.wait()的函数,导致主进程一直在等待着 b 进程的结束,但是 b 进程一直结束不了,因此主进程结束不了,导致产生 a 进程的僵尸进程,场景三的时候,同场景一原理一样,a 和主进程同时结束,这里也是相当于主进程和 a 子进程同时退出,不会产生僵尸进程,最后一个场景,也是和场景二一样。因此,归根结底,就是保证不会一直在运行的子进程和主进程同时退出,就不会导致产生僵尸进程,不知道这个解释是不是正确,请大家来帮我看看。
2918 次点击
所在节点    Python
3 条回复
neoblackcap
2017-10-31 10:57:52 +08:00
我来一一说明你的问题
1. Popen.wait()只是告诉主进程要等待子进程,真正的意义是主进程要去清理子进程结束后剩余的信息,主进程不一定会接着退出。
2. 僵尸进程是由于主进程没有调用 wait 而导致的。那么主进程没有调用 wait 是不是一定会出现僵尸进程呢?答案是不一定,因为主进程早于子进程退出,那么子进程就成了孤儿进程,孤儿进程会被 init 进程(pid 1)托管然后 init 进程会对这些孤儿进程进行 wait。
2.1 回到你的问题,若有调用 wait,那么这个子进程必然不会成为僵尸进程。
2.2 剩下没有 wait 的子进程但是又没有成为僵尸进程显然就是主进程早于它退出了,它被 init 收养罢了
2.3 子进程成为了僵尸进程,但是主进程没有退出,显然就是主进程没有调用 wait 罢了。
3. 你的分析还算是对,但是你的结论却有问题,这个你还是得看我的第二点。要不然你的结论如何解释你的第一个场景呢?
linhanqiu
2017-10-31 16:24:17 +08:00
@neoblackcap 多谢,
lolizeppelin
2017-10-31 22:19:30 +08:00
不用乱想 这些都不是 python 的知识
自己看 linux 相关系统调用就明白了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/402171

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX