如何控制 ntoskrnl.exe!MiWalkPageTablesRecursively 的 CPU 使用率

Vij*_*jay 6 windows cpu kernel

内核跟踪高 CPU 使用率的帖子之后,我以为我已经调试了一个一直困扰我的问题,即系统进程 20-30% 的一致 CPU 使用率。请参阅我之前的帖子

我设置了 Windows 性能分析器,并且能够跟踪到这个过程: WPA 跟踪日志 我认为这与通过函数名称猜测的页面文件有关,并禁用了我的页面文件,然后重新启动,但 Windows 拥有页面文件并抛出错误。所以我创建了一个大约 100MB - 2048MB 的小页面文件。

这似乎已经解决了几个星期的问题,但现在它又来了,即使页面文件只有 2GB。它似乎发生在系统启动一段时间后。当前正常运行时间为 8 天。

如果任何内核专家可以就我接下来应该尝试什么提供建议,我很乐意这样做。

然而,进程资源管理器在系统映像下显示了一个不同的线程。我不知道如何调和这种差异:

初始化AnsiStringEx

进程浏览器通常显示上述内容,但在其他时候它可以显示调试过滤器状态......等。

在此处输入图片说明

(我相信它总是 ThreadID 56)但是几个跟踪日志似乎总是显示我们在上面看到的问题。

编辑

根据 RAM 的要求添加了图像。这是在问题不存在的全新重启之后。

内存使用 流程细节工作集

博客推荐的配置符号路径以加快符号加载

进程浏览器

procexp 符号路径

水杨酸

WPA 符号路径

缓存文件夹的文件大小

符号信息

在系统上发现多个版本的 dbghelp.dll。当前指向系统,但不知道它应该指向哪个。

dbghelp.dll 版本


更新

按照查找Zombie Processes的链接后,我发现了以下数据(已截断以删除次要条目)

374 total zombie processes.
334 zombies held by explorer.exe(1768)
    298 zombies of Fences.exe
    9 zombies of LogonUI.exe
    7 zombies of chrome.exe
10 zombies held by ctfmon.exe(4568)
    2 zombies of chrome.exe
7 zombies held by dopus.exe(27672)
    3 zombies of AcroRd32.exe
2 zombies held by RuntimeBroker.exe(12184)
    2 zombies of WWAHost.exe
1 zombie held by SkypeHost.exe(190152)
    1 zombie of SkypeApp.exe
1 zombie held by SecurityHealthService.exe(4536)
    1 zombie of MsMpEng.exe
1 zombie held by svchost.exe(1988)
    1 zombie of userinit.exe
Run Code Online (Sandbox Code Playgroud)

这意味着 FENCES.exe 是原因,因此我已更新该程序并将稍后再次检查。还禁用了协同作用以确保这不是原因。

更新 2

在重新启动和更新围栏之后。僵尸进程的问题仍然存在,所以我将不得不卸载围栏来解决这个问题。

这是围栏的版本

在此处输入图片说明

以及重新启动后的僵尸进程列表。

16 total zombie processes.
7 zombies held by explorer.exe(9484)
    5 zombies of Fences.exe
    1 zombie of GoogleUpdateCore.exe
    1 zombie of DropboxUpdate.exe
1 zombie held by svchost.exe(1788)
    1 zombie of userinit.exe
Run Code Online (Sandbox Code Playgroud)

边注

如果我们拥有能够帮助处理所有这些事情的软件 AI,那不是很酷吗?

Jam*_*han 7

快速回答:减少日常工作要做。我认为这意味着要么一次使用更少的虚拟地址空间,要么添加更多的 RAM。

详细信息:首先,您看到的例程MiWalkPageTablesRecursively与页面文件几乎没有直接关系,而是与页表有关。页表是内存中的结构(并且存在于所有 Windows 系统中,无论页面文件配置如何)。每个进程都有一组页表,还有一组用于操作系统的地址空间(“内核空间”)。

页表由页表条目组成;进程定义的虚拟地址空间的每一页(4K)都有一个 PTE。通过“定义”,我的意思是它包括进程的映射和私有提交地址空间,以及 AWE 区域(如果有);它不包括保留或空闲地址空间 - 如果您尝试读取或写入它们会引发访问冲突的区域。

(顺便说一句:即使您没有页面文件,您不仅仍然会有页表。即使您没有页面文件,您仍然会有分页和与磁盘之间的页面错误。)

这里的问题可能不是MiWalkPageTablesRecursively. 毕竟,自 NT 3.1 以来,此功能(或其他名称的等效功能)已成为 Windows 的一部分。事实上,它必须做很多工作。这可能意味着它经常被调用。

在堆栈较早的例程中可以看到为什么会出现这种情况的线索。(也就是说,更接近 WPA 显示的顶部。)MiWalkPageTablesRecursively在这种情况下MiWalkPageTables,看起来像是 的调用者是 ,而后者又被 调用 MiAgeWorkingSet,而后者又被 调用 MiTrimOrAgeWorkingSet,而后者又被 调用 MiProcessWorkingSets,其中反过来又被...调用,这就是我们需要做的。

Windows 系统中的每个进程都有一个称为“工作集列表”的结构。这是由于进程的页面错误而进入 RAM 的所有物理页号的列表。该线程(“平衡集管理器”线程)每秒被唤醒一次,以对每个进程的工作集进行清理和维护。因此MiProcessWorkingSets遍历进程,依次处理每个进程的工作集。

对于系统中的每个进程,MiProcessWorkingSets调用MiTrimOrAgeWorkingSet. 此例程名称指的是“修剪”工作集(这意味着识别长期不使用的页面并将它们从进程中驱逐,以便在 RAM 中为其他事情腾出空间),或“老化”工作集,这意味着增加“年龄”自上次扫描以来未访问过的每个工作集列表条目上的计数器,或者如果已访问则将计数器清零。(该名称指的是会计中执行的“老化”任务,通常是每月或每天。)然后“修剪”函数使用“老化”计数器来识别最不使用的页面。

从以MiTrimOrAgeWorkingSet结束的事实MiWalkPageTablesRecursively,我们可以推断他们正在扫描页表定义的虚拟地址空间以查找工作集中的页面。现在考虑:MiTrimOrAgeWorkingSet处理每个进程所需的时间将大致与进程的虚拟地址空间的大小成正比。并且每次通过所需的总时间MiProcessWorkingSets将大致与进程数成正比。

这个东西要么处理一个进程工作集中的大量页面,要么它不得不处理很多进程。

还有……怎么会这么忙?它不会在工作集老化之前“修剪”它们,并且它“修剪”工作集的数量取决于 RAM 压力——也就是说,你在 RAM 上有多短。

您的系统内存不足吗?请发布任务管理器性能选项卡的快照 | 内存页面,加上按工作集列排序的详细信息页面;加上 Resource Monitor 的 Memory 选项卡,按 Hard Faults 列排序;和 RAMmap 的使用计数页面。

另外,请发布更多您拥有的 WPA 跟踪,以显示更多“深度”的调用。或者将 .etl 文件发布到某处的共享服务上,并在此处链接到它。(先将其压缩 - 它们压缩得非常好。)

旁白:为什么 WPA 和 Process Explorer 之间的例程名称不匹配

至于例程名称,真正的问题是“为什么 Process Explorer 中显示的例程名称完全错误”。在您的情况下有两个原因,您必须解决这两个问题。

第一个问题是,您似乎没有为 Process Explorer 正确配置符号。为 Windows Performance Analyzer 配置它们是不够的。

你没有这个权利的一个明确迹象是“系统”进程中的所有或几乎所有线程都显示一个模块名称(something.sys或something.exe,通常是ntoskrnl.exe)后跟一个偏移量,例如+0x245- 在您的屏幕截图中。可以看到一些这样的东西,但你应该看到一大堆ntoskrnl!例程名称后跟偏移量。

为了解决这个问题,看到这个页面Windows性能分析领域指南。您需要设置 Process Explorer 的符号搜索路径 - 您可以使用为 WPA 设置的相同符号文件路径 - 您需要将 ProcExp 指向 Windows 调试工具附带的 DLL。所以你需要安装调试工具——不是你直接使用调试器,而是进程资源管理器需要那个 DLL。

造成差异的第二个原因是,即使您为 Process Explorer 正确设置了符号文件,它显示的例程名称通常也不会与性能分析器识别的内部级例程的名称相匹配。但是,您应该在堆栈开头附近的例程名称上找到匹配项(显示在例程调用树的顶部,如 WPA 所示)。

例如 - 在您的情况下,第一个感兴趣的例程是KeBalanceSetManager. (之前的两个对于系统进程中的每个线程都是相同的,但是KeBalanceSetManager该例程是该线程的“顶级”例程。)一旦您正确配置了符号,进程资源管理器应该向您显示一个线程,该线程作为“起始地址”,如下所示:

这里

Process Explorer 无法向您显示,MiWalkPageTablesRecursively因为从记录为线程起始地址的内容开始大约有六个调用到堆栈中,并且它甚至不是当前最内部的例程(即它不在堆栈顶部)。此类信息(即使很容易获得,但并非如此)会变化太快而无法在 Process Explorer 显示中使用,因此它不会尝试。

注意:即使使用正确的符号,在系统进程中找到一些线程显示 eg 的“起始地址”的情况并不少见GemCCID.sys+0xd138,正如您将在我的示例中看到的那样。有问题的模块 (GemCCID.sys) 显然不是 Microsoft 为其提供符号文件的模块,因此 Process Explorer 只需要说“线程起始地址位于此文件中代码开头的 0xd138 字节处,这就是我的全部知道这件事。”

希望这可以帮助!如果您还有其他问题,请告诉我。


归档时间:

查看次数:

3192 次

最近记录:

5 年,6 月 前