我只是在玩 WSL 上的僵尸进程。我写了一个非常简单的程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define CHILD 0
int main(){
int p;
p = fork();
if(p == CHILD){
printf("Kind-PID: %u\n", getpid());
exit(1);
} else if(p > CHILD){
sleep(30);
}
else return EXIT_FAILURE;
return EXIT_SUCCESS;
}
虽然我可以在本机 Linux 上使用ps
看到僵尸进程,但在 WSL 上看不到僵尸进程。谁能解释为什么?
免责声明:我对 WSL 的内部运作一无所知。我对 Windows 进程生命周期细节的了解只是快速谷歌搜索的结果。随时纠正我。
在 Linux 中,进程状态以 Unix 风格使用其进程表条目进行跟踪,该条目确定其 PID 号。因此,当一个进程死亡时,进程表条目不能被清除,直到(真正的或被采用的)父进程读取死进程的退出代码 - 保持 PID 号被占用。表明进程已经死亡但尚未读取退出代码的进程表条目被称为处于僵尸状态。系统中的所有进程都可以访问此状态和进程表中的各种其他信息位。
在 Windows 中,进程信息由进程句柄访问。此外,正在运行的进程也有一个进程 ID。当进程死亡时,PID 号可以立即回收,因为退出代码将与死亡进程的句柄一起存储,与 PID 号分开管理。与 PID 号不同,进程句柄在其持有者关闭它之前将一直有效;它所指的进程的死亡不会使进程句柄无效。
为了忠实地显示 WSL 中“僵尸”状态的等价物,WSL
ps
命令必须检查所有其他 WSL 进程的句柄以找到僵尸进程,然后以某种方式获取进程曾经拥有的 PID 号它们是活动的 - 将不再存在的信息,除非 WSL 子系统在进程活动时专门从 Windows 进程表中复制它。但是进程句柄不一定必须是公共信息:根据 WSL 的实现方式,WSL 进程可能只能看到它自己的子进程的僵尸,只能看到属于同一用户的僵尸,或者可能是任何用户的僵尸。仅 WSL 进程。为了重现 Unix 风格的僵尸进程的外观,WSL 可能必须保留系统上每个 WSL 进程的句柄。
但理论上,死 WSL 进程的 Windows PID 可能会被回收到另一个活进程,而死 WSL 进程的(实际或采用的)父进程在读取死进程的退出代码之前会花些时间。那么 WSL 应该报告什么作为僵尸的 PID 呢?报告已经被另一个生命进程使用的 PID 显然是错误的做法;为僵尸报告与活着时实际不同的 PID 也不正确。
由于实际上您对僵尸进程几乎无能为力,并且僵尸进程不会弄乱 PID 编号空间,因此对于 WSL来说,对于像这样的命令,完全不尝试完全重现僵尸进程的概念
ps
可能是一个有效的选择.