11 bash process signals zombie-process
我正在挖掘不同的来源,但找不到对儿童收割解剖结构的良好描述。这是我想了解的一个简单案例。
$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17 00:00:00 bash
14248 12126 S pts/17 00:00:00 bash
14249 12126 S pts/17 00:00:00 sleep 100
14251 14250 S pts/17 00:00:00 grep --color=auto 12126
$ kill -2 14248
$ ps ax -O pgid | grep $$
12126 12126 S pts/17 00:00:00 bash
14248 12126 Z pts/17 00:00:00 [bash] <defunct>
14249 12126 S pts/17 00:00:00 sleep 100
14255 14254 S pts/17 00:00:00 grep --color=auto 12126
Run Code Online (Sandbox Code Playgroud)
为什么僵尸在等孩子?
你能解释一下这个吗?我是否需要了解 C 并阅读 Bash 源代码才能对此有更广泛的了解,或者是否有任何文档?我已经咨询过:
man bash
GNU bash,版本 4.3.42(1)-release (x86_64-pc-linux-gnu)
Linux 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Gil*_*il' 17
僵尸不是在等待它的孩子。像任何僵尸进程一样,它会一直存在,直到它的父进程收集它。
您应该显示所有涉及的进程以了解正在发生的事情,并查看 PPID。使用这个命令行:
ps -t $(tty) -O ppid,pgid
Run Code Online (Sandbox Code Playgroud)
您要杀死的进程的父进程是cat
. 发生的情况是 bashcat <( sleep 100 & wait )
在子 shell 中运行后台命令。由于这个子shell 所做的唯一一件事就是设置一些重定向,然后运行一个外部命令,这个子shell 被外部命令替换。这是纲要:
fork
执行后台命令cat <( sleep 100 & wait )
。
pipe
创建一个管道,然后fork
创建一个子进程来运行进程替换sleep 100 & wait
。
fork
运行sleep 100
。由于孙子不是交互式的,后台进程不会在单独的进程组中运行。然后孙子等待sleep
退出。setpgid
(它是交互式 shell 中的后台作业,因此它拥有自己的进程组),然后execve
运行cat
. (我有点惊讶后台进程组中没有发生进程替换。)cat
进程正在运行,它对任何子进程一无所知,也没有业务调用wait
。由于孙子的父母没有收获,孙子作为僵尸留在了后面。cat
退出——要么是因为你杀死了它,要么是因为sleep
返回并关闭管道以便cat
看到其输入的结束。那时,僵尸的父母死了,所以僵尸被 init 收集并被 init 收割。如果您将命令更改为
{ cat <( sleep 100 & wait ); echo done; } &
Run Code Online (Sandbox Code Playgroud)
然后cat
在一个单独的进程中运行,而不是在原始 bash 进程的子进程中运行:第一个子进程必须留在后面才能运行echo done
。在这种情况下,如果您杀死孙子,它不会像僵尸一样继续存在,因为子子(此时仍在运行 bash)会收获它。
另请参阅linux 如何处理僵尸进程和僵尸可以有孤儿吗?孤儿们会因为收割丧尸而感到不安吗?
僵尸不是在等孩子。相反,僵尸是已经死亡的进程(被它自己杀死了,或者被杀死了——就像你的例子一样),它的代码、数据和堆栈被释放了,现在只包含它的退出代码,等待它的父级调用wait(2)
来检索它(从而最终从进程表中完全清除进程条目)
在您的示例中,当睡眠结束(或被杀死)时,父母将读取退出状态,并收获僵尸。详情见上文wait(2)
。
归档时间: |
|
查看次数: |
2753 次 |
最近记录: |