Linux僵尸进程会被杀死吗?

Linux僵尸进程会被杀死吗?,第1张

什么是僵尸

首先要明确一点,僵尸进程的含义是:子进程已经死了,但是父进程还没有wait它的一个中间状态,这个时候子进程是一个僵尸。正常情况下子死,父wait,清理掉子进程的task_struct,释放子进程的PID:

Linux僵尸进程会被杀死吗?,poYBAGLvewGAHulxAADi0s3XoDg365.png,第2张

编译上述程序,运行,我们看到2个a.out进程:

Linux僵尸进程会被杀死吗?,pYYBAGLvexyABEAxAAIYnnzFyhw991.png,第3张

杀死子进程4578,看到父进程的打印:

Linux僵尸进程会被杀死吗?,pYYBAGLvezmAcJHXAAFDNhNe2Gc860.png,第4张

之后,4578会消失,因为父进程执行到了wait,也知道了子进程是被信号2杀掉的。

但是如果子进程死了,父进程不执行到wait,比如把上图中的"#if 0"改为"#if 1",杀死子进程后,子进程就是一个僵尸:

Linux僵尸进程会被杀死吗?,poYBAGLve1CAZa5OAADgZchKiDA714.png,第5张

我们重新运行,当我们用kill -2杀掉子进程4628后,我们发现4628成为一个僵尸,状态变为Z+,名字上也加了一个棺材[],成为[a.out]:

Linux僵尸进程会被杀死吗?,poYBAGLve2mANd-eAAEjeAj05mc783.png,第6张

僵尸不可能被杀死

我们看到上面4628是个僵尸很不爽,所以我们想把它干掉,据说Linux有个信号9,神挡杀神,佛挡杀佛,我们现在来用kill -9干掉4628:

Linux僵尸进程会被杀死吗?,pYYBAGLve3-AenM0AAEzr1MV4kM809.png,第7张

从上图可以看出,我们把4628用kill -9捅了好多刀,但是最后看4628这个僵尸,还是没有消失。

因为僵尸已经是死了,它不可能再次被杀死,你给它捅一万刀,它也是个死人,不可能再次死!

僵尸不可能被杀死,因为它已经死了!只等父进程来wait清理尸体了。

一个僵尸可以被杀死的假象

下面的这个程序证明“僵尸可以被杀死”

Linux僵尸进程会被杀死吗?,pYYBAGLve5qAULk8AADDYCfucEU363.png,第8张

我们在主线程里面,pthread_create()创建线程后,pthread_exit()退出,这个时候我们会发现,在ps命令里面,a.out显示为一个僵尸:

Linux僵尸进程会被杀死吗?,pYYBAGLve7OADC_nAAEjKQVLLwQ964.png,第9张

这个时候我们来杀死4730这个僵尸:

kill -9 4730

我们会惊奇地发现,4730真地会从ps命令里面消失!

Linux僵尸进程会被杀死吗?,pYYBAGLve8iAO4pSAABrtF0CgyA618.png,第10张

我们把时间轴拉回调用"kill -9 4730"之前。刚才我们“看起来”能杀死僵尸的本质原因是,当主线程4730调用pthread_exit()退出后,主线程4730的状态确实是僵尸了,但是该进程里面的4731线程,却没有死:

Linux僵尸进程会被杀死吗?,poYBAGLve-mASDHOAABUL8QN9wo642.png,第11张Linux僵尸进程会被杀死吗?,poYBAGLve--AUffgAAC8wpVBIQc579.png,第12张

看看4731:

Linux僵尸进程会被杀死吗?,poYBAGLvfAaANz6pAADGDjfVLHI847.png,第13张

4731是活着的,证明整个进程并没有挂。

那么,根据POSIX标准关于信号(signal)的定义,当我们执行kill -9 4730(4730是4730和4731的TGID,也是整个进程用户态视角的PID)的时候,是要杀死整个4730进程的,所以这个时候4731被我们杀死,整个进程就都死了,这个时候,执行到父进程的wait逻辑,导致僵尸消失。

所以,在本例中,kill -9 4730看起来是"杀死了僵尸”,实际是杀死了4731,导致整个进程死。



审核编辑:刘清

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/dianzi/3001202.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)

保存