上次,我介绍了限制以及如何度量两个关键窗口管理器资源USER对象之一的使用情况。这一次,我将介绍其他关键资源,GDI对象。与往常一样,我建议您在此之前阅读以前的帖子,因为与USER和GDI资源相关的一些限制是基于我所介绍的限制。这里是我的另一个推动Windows的限制职位的完整索引:
GDI对象
GDI对象表示图形设备接口资源,如字体,位图,画笔,笔和设备上下文(绘图表面)。与USER对象一样,窗口管理器将进程限制为至多10,000个GDI对象,您可以使用-g开关使用Testlimit来验证该对象:
您可以在其Process Explorer进程属性对话框的Performance页面上查看单个进程的GDI对象使用情况,并将GDI对象列添加到Process Explorer以观察跨进程的GDI对象使用情况:
与USER对象一样,16位互操作性意味着USER对象具有16位标识符,每个会话限制为65,535个标识符。当Testlimit达到Windows Vista 64位系统上的限制时,出现桌面:
请注意它所在的左下角的“开始”按钮,但屏幕顶部的任务栏的其余部分。桌面变黑了,边栏已经失去了大部分的颜色。你的里程可能会有所不同,但你可以看到奇怪的事情开始发生,可能使得不可能以可靠的方式与桌面交互。以下是按下“开始”按钮时显示切换的内容:
与USER对象不同,GDI对象不是从桌面堆分配的; 相反,在没有安装终端服务的Windows XP和Windows Server 2003系统上,它们将从常规分页池中分配; 在从会话会话池中分配的所有其他系统上。
内核调试器的“!vm 4”命令会转储一般虚拟内存信息,包括输出结尾的会话信息。在Windows XP系统上,它显示会话分页池未被使用:
在没有终端服务的Windows Server 2003系统上,输出类似:
因此,这些系统上的GDI对象内存限制是页面缓冲池的限制,正如我以前的文章“ 推动Windows的限制:分页和非分页池”所述。但是,如果终端服务安装在相同的Windows Server 2003系统上,则可以从非零会话池中看到GDI对象来自会话池:
上述输出中的!vm 4命令还显示会话分页池最大值和会话池大小,但会话分页池最大值和会话空间大小在Windows Vista及更高版本上不显示,因为它们是可变的。这些系统上的会话分页池使用率受其可增长的地址空间量或系统提交限制(以较小者为准)的上限限制。以下是Windows 7系统上命令的输出,显示会话中当前会话分页池的使用情况:
正如您所期望的那样,主要的交互式会话,即会话1正在消耗最多的会话分页池。
您可以将Testlimit工具与“-g 0”开关一起使用,以查看用于GDI对象的存储空间耗尽时的情况。在-g是Testlimit分配的GDI位图对象的大小后指定的数字,但大小为0的Testlimit只需尝试并分配可能的最大对象。这是32位Windows XP系统的结果:
在没有安装终端服务的Windows XP或Windows Server 2003上,您可以使用Windows Driver Kit(WDK)中的Poolmon实用工具通过其池标记查看GDI对象分配。当Testlimit耗尽WIndows XP系统上的页面缓冲池时,Poolmon的输出看上去像这样,当按字节分配(在Poolmon显示中键入'b'按分配的字节排序),通过推论表明Gh05是位图的标记Windows Server 2003上的对象:
在安装了终端服务的Windows Server 2003系统上,在Windows Vista及更高版本上,必须使用Poolmon和/ s开关来指定要查看的会话。以下是在安装了终端服务的Windows Server 2003系统上执行的Testlimit:
命令“poolmon / s1”显示分配贡献最大的标记。您可以在顶部看到Gh15标记,显示不同的池标记正被用于位图分配:
请注意,Testlimit如何在Windows XP系统上分配大约58 MB的位图数据(该数字不占用位图对象的GDI内部开销),但Windows Server 2003系统上只有10 MB。较小的数字来自于Windows Server 2003终端服务器系统上的会话池只有32 MB,这大约是Poolmon显示归因于Gh15标记的内存量。“!vm 4”的输出确认Session1的会话池已被占用,随后尝试从会话池分配GDI对象失败:
您也可以使用!poolused内核调试器命令来查看会话池的使用情况。首先,使用带/ p开关的.process命令和连接到会话的进程对象的地址切换到正确的会话。要查看特定会话中正在运行的进程,请使用!sprocess命令。下面是同一台Windows Server 2003系统上的!poolmon的输出,其中poolused的“c”选项用输入的字节对输出进行排序:
不幸的是,窗口管理器的堆标签和它们代表的对象之间没有公共映射,但是内核调试器的poolused命令使用调试器安装目录下的triage.ini文件来打印更多关于标签的描述性信息。该命令报告Gh15是GDITAG_HMGR_SPRITE_TYPE,这只是稍微有点帮助,但其他更清楚。
幸运的是,大多数GDI和USER对象问题仅限于一个特定进程触及每个进程10000个对象的限制,因此更高级的调查来确定哪个进程负责耗尽会话池或分配GDI对象以耗尽分页池是不必要的。
下一次,我将看看系统页面表项(系统PTE),这是另一个可能受到限制的关键系统资源,特别是在Windows Server 2003系统上的远程桌面会话上。