![如何识别导致每个退出的进程变成僵尸、污染页表和活动未使用的内存的驱动程序?](https://linux22.com/image/1705438/%E5%A6%82%E4%BD%95%E8%AF%86%E5%88%AB%E5%AF%BC%E8%87%B4%E6%AF%8F%E4%B8%AA%E9%80%80%E5%87%BA%E7%9A%84%E8%BF%9B%E7%A8%8B%E5%8F%98%E6%88%90%E5%83%B5%E5%B0%B8%E3%80%81%E6%B1%A1%E6%9F%93%E9%A1%B5%E8%A1%A8%E5%92%8C%E6%B4%BB%E5%8A%A8%E6%9C%AA%E4%BD%BF%E7%94%A8%E7%9A%84%E5%86%85%E5%AD%98%E7%9A%84%E9%A9%B1%E5%8A%A8%E7%A8%8B%E5%BA%8F%EF%BC%9F.png)
我有一个相当新的 Windows 11 Pro 安装,大约一周。我注意到我的 RAM 使用量不断上升。我担心,因为 procexp 读数与报告的总使用 RAM 值不匹配,差异因子为 4 或更多。
我检查了 RAMMap,发现进程永远无法完成。所有已创建的进程都无法完成。它们占用内存,这些内存主要被报告为未使用的活动内存和页表内存。
为了实现以下目的,我创建并退出了 100000 个 cmd.exe 进程。我使用了以下命令:
FOR /L %i IN (1,1,100000) DO cmd /c echo %I
注意高页表和未使用的活动内存读数。
所有已退出的进程均显示在 RAMMap 中
此时,我能够找到有关此问题的更多信息,主要是https://randomascii.wordpress.com/2018/02/11/zombie-processes-are-eating-your-memory/
然而,使用 FindZombieHandles 进行诊断并没有揭示出是什么阻碍了这些进程。
c:\Programs\blogstuff\FindZombieHandles\prebuilt>FindZombieHandles.exe
110416 total zombie processes.
6 total zombie threads.
222 zombies held by Taskmgr.exe(6640)
137 zombies of cmd.exe - process handle count: 137 - thread handle count: 0
25 zombies of firefox.exe - process handle count: 25 - thread handle count: 0
11 zombies of dllhost.exe - process handle count: 11 - thread handle count: 0
7 zombies of backgroundTaskHost.exe - process handle count: 7 - thread handle count: 0
5 zombies of RuntimeBroker.exe - process handle count: 5 - thread handle count: 0
5 zombies of EngHost.exe - process handle count: 5 - thread handle count: 0
4 zombies of WmiPrvSE.exe - process handle count: 4 - thread handle count: 0
4 zombies of ctfmon.exe - process handle count: 4 - thread handle count: 0
4 zombies of consent.exe - process handle count: 4 - thread handle count: 0
3 zombies of taskhostw.exe - process handle count: 3 - thread handle count: 0
3 zombies of OpenConsole.exe - process handle count: 3 - thread handle count: 0
2 zombies of mobsync.exe - process handle count: 2 - thread handle count: 0
2 zombies of DbgX.Shell.exe - process handle count: 2 - thread handle count: 0
1 zombie of WindowsTerminal.exe - process handle count: 1 - thread handle count: 0
1 zombie of svchost.exe - process handle count: 1 - thread handle count: 0
1 zombie of StartMenuExperienceHost.exe - process handle count: 1 - thread handle count: 0
1 zombie of sppsvc.exe - process handle count: 1 - thread handle count: 0
1 zombie of SearchHost.exe - process handle count: 1 - thread handle count: 0
1 zombie of pwsh.exe - process handle count: 1 - thread handle count: 0
1 zombie of msedgewebview2.exe - process handle count: 1 - thread handle count: 0
1 zombie of explorer.exe - process handle count: 1 - thread handle count: 0
1 zombie of conhost.exe - process handle count: 1 - thread handle count: 0
1 zombie of audiodg.exe - process handle count: 1 - thread handle count: 0
9 zombies held by svchost.exe(12660)
9 zombies of EngHost.exe - process handle count: 9 - thread handle count: 0
2 zombies held by nvcontainer.exe(4908)
2 zombies of rundll32.exe - process handle count: 2 - thread handle count: 0
2 zombies held by svchost.exe(4620)
2 zombies of explorer.exe - process handle count: 2 - thread handle count: 2
1 zombie held by atieclxx.exe(3504)
1 zombie of atieah32.exe - process handle count: 1 - thread handle count: 1
1 zombie held by NVDisplay.Container.exe(2896)
1 zombie of dbInstaller.exe - process handle count: 1 - thread handle count: 1
1 zombie held by svchost.exe(2268)
1 zombie of userinit.exe - process handle count: 1 - thread handle count: 0
ObjExp.exe 在这种情况下也无济于事。它显示了正确的对象数量,但无法识别句柄(请注意句柄的数量比对象的数量小得多)
文件、令牌和事件对象也遵循计数,虽然我不确定如何解释这一点,但我认为它们只是为每个进程自然创建的(例如文件句柄是图像)
此时我很确定问题不在于任何用户空间进程,而是由某些系统组件/驱动程序引起的。
我尝试使用连接到内核的 WinDbg 搜索这些句柄,并将所有驱动程序上的驱动程序验证程序设置为 Misc。我尝试执行,!handle 0 3 0 Process
但没有发现任何异常,而且输出速度太慢(每行几秒),无法获得完整的读数。我也尝试过,!process 0 0
但列出的进程都没有显示异常数量的句柄,尽管有些显示 0 个句柄,我认为这可能是权限问题。
我现在不知所措,虽然这个问题并不严重,但对于我通常产生大量进程的工作负载来说,它确实很烦人。昨天正常使用电脑 10 小时后,我产生了 20GB 未使用的活动内存和页表内存(被僵尸进程占用),有超过 2 万个进程。
driverquery /v
输出(以及明显的潜在违规者?无论我生成多少个 cmd 进程,输出总是相同的):https://pastebin.com/CcT7rzbJ
该问题在安全模式下不会出现。
更新 2:poolmon 没有显示任何异常。创建 10000 个 cmd.exe 进程的唯一作用是将 Proc 标记的对象放入前 10 名,这是预料之中的,因为这会处理进程对象。我认为我无法使用 poolmon 找到此泄漏,因为句柄占用的空间可以忽略不计,我甚至不确定它们是否会反映在内存使用中。
更新 3:我用 DDU 删除了 NVIDIA GPU 驱动程序,并使用 NVCleanstall 重新安装,但没有遥测。NvModuleTracker 不是问题所在。由于它使用 PsSetCreateProcessNotifyRoutineEx,所以这是有可能的,但事实证明它处理得当。我不知道如何检查哪些其他驱动程序使用此回调...
更新 4:我禁用了 BAM 和 DAM,但问题仍然存在。
更新 5:我对任务管理器和 rammap 中显示的进程进行了基本的交叉检查,据我所知,这可以识别出第一个被暂停的进程以及自问题出现之前就一直在运行的进程。不过这里没有太多有用的信息,基本上说这是一个驱动程序。
更新 6:我通过在 BIOS 中禁用 AMD iGPU 并运行 AMD Cleanup Utility 来删除驱动程序,解决了该问题。但是,目前还不清楚如何识别将来的类似问题,因此这个问题仍然悬而未决。
答案1
最近这种情况似乎经常发生,所以我会在社区 wiki 中留下一些相关链接,以防出现更多信息。似乎有几个人通过降级或卸载 AMD 驱动程序成功解决了这个问题。
- Docker GitHub
"docker context ls" leaves behind zombie processes #14027
:https://github.com/docker/for-win/issues/14027 - AMD 社区论坛
Memory leak on Zen4?
(使用 poolmon 进行诊断):https://community.amd.com/t5/drivers-software/memory-leak-on-zen4/td-p/662281 - Docker GitHub
Memory Leak #13929
:https://github.com/docker/for-win/issues/13929
答案2
我最初以为是 Docker,因为里面有成千上万个docker.exe
进程com.docker.cli
句柄拉姆地图,但即使卸载了 Docker 桌面,问题仍然会出现,似乎是由AMD Radeon GPU 驱动程序(名为:AMD Adrenaline。v24
已知存在此问题。目前最新版本是v24.4.1
)。
如果我没记错的话(当然有可能),每个有这个问题的人都会有AMD 肾上腺素已安装。
v24.*
您可以通过卸载并安装v23.10.2
已确认没有 Bug 的驱动程序版本来确认是否存在该问题。您可以在此处下载:https://www.amd.com/en/resources/support-articles/release-notes/RN-RAD-WIN-23-10-2.html
仅供参考,禁用 iGPU 似乎可以解决问题(我仍在测试,但目前看来效果不错)。即使不能解决,至少似乎可以显著提高僵尸句柄的数量。
我必须提一下僵尸进程句柄在解决这一问题方面发挥了重要作用,并且Bob 的帮助。
编辑只是想报告一下,自从我两天前禁用集成显卡以来,这个问题似乎已经消失了。