WindowsNT中,GDI资源的管理
来源:互联网 发布:战地1942 mac 下载 编辑:程序博客网 时间:2024/05/29 07:00
WindowsNT中,GDI资源的管理
结论
经过上面的分析,我们可以知道,在Windows 2000/2003 操作系统中,每个进程可以创建的GDI对象,受限于三个方面因素:系统本身的两个方面的限制和Windows注册表中设置的最大值限制。
首先,每个进程可以创建的GDI对象数,在理论上为64K,但是在Windows 2000中,系统将客户可以创建的GDI句柄数硬设置为不能超过16K,而事实上当GDI对象数达到12K之后,系统即不正常;在Windows 2003中,系统放宽了对GDI对象数的限制,使得每个进程可以使用的GDI对象数接近64K;
其次,每个进程可以创建的GDI对象数,还受限于操作系统中GDI对象总数;在Windows 2000中,当系统中总的GDI对象达到15900以后的某个值后,进程就不能再创建新的GDI对象了;在20003中,这个值增加到63700以后的某个值。但是,到底是哪个值,则不固定。
最后,进程可创建的最大GDI对象数目还受限于注册表中HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows下的"GDIProcessHandleQuota" 项所设置的值,该值设置了Windows中每个进程可以创建的最大GDI对象数,在Windows 2000及2003系统中,其默认均为10000,这也就说明了当程序创建的GDI对象数达到9999之后界面为什么会混乱。
http://blog.chinaunix.net/uid-171942-id-2819968.html
GDI资源为什么会耗尽呢,到哪种程度才表现为耗尽呢?
为了回答这一问题,我们用Windows自带的任务管理器观察后发现,当程序界面开始混乱时,进程的GDI对象值为9999,那么为什么GDI对象达到9999后界面才发生混乱呢,带着这个疑问,我查找了一些资料,简单的了解到了Windows对GDI对象的管理方式。
GDI对象,实际上是Windows系统维护的一些数据结构。微软基于稳定性和健壮性考虑,将所有GDI对象的管理权都交给Windows系统的对象管理器管理,用户只能通过系统返回的“句柄”来操作这些对象。
在Windows 2000中,句柄实际上是一个DWORD类型的值。该DWORD值是一个32比特位的数据,它又分为两个部分:Table Index及Uniqueness Identifier,他们各占16位,因此,在理论上来说,Windows中的每个进程,所能访问的GDI对象的最大值是64K。然而,在Windows 2000中,客户句柄的最大数目被硬设置为16384 (16K);
然而,在Windows 2000中,既便客户句柄的最大数目被硬设置为16384,那么为什么在实际中GDI对象增加到9999后,程序界面就开始混乱了呢?原来,在Windows2000中,每进程的GDI对象的最大值又被默认为10000——据微软资料显示,之所以设置为10000,是为了阻止“Bad”程序分配过多的资源,因此,当GDI对象达到9999之后,程序就不能再创建新的GDI资源,这样,每次都使用新建资源来绘制界面的程序就产生混乱了。
不过,在Windows 2000及以后的操作系统中,每个进程可以创建的GDI对象的最大值,是可以通过修改注册表来重新设置的,在Windows 2000中,该注册表项所为:HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows下的"GDIProcessHandleQuota"。设置完新的值后,重启计算机后,系统中每进程可以使用的GDI对象数就会变成你新设置的数。
然而,上述说法并不完全正确!
据SYBASE的一份资料显示(http://www.sybase.com/detail?id=1019174),在Windwos2000中,只可以对”GDIProcessHandleQuota”值进行微调,如果设置的值超过15000,系统就变得不稳定。事实上,我在Windows 2000中进行了测试,当GetGuiResources函数的返回值为12288(12K)时,就已经不能创建新的GDI对象了,也就是说,在Windows 2000中当一个进程总的GDI对象数达到12288以后,就不能再创建新的GDI对象了。
那么,在Windows 2000中,进程所能创建的GDI对象数,是每个进程独立的,还是要受限于Windows操作系统呢?为此,我写了一个check程序,该程序批量创建指定数目的BRUSH对象,并统计本进程的GDI对象数及系统中总的GDI对象数,其运行界面如下(这里图显示不出来,不过无关紧要)
其中统计系统中总的GDI对象的代码如下:
int GetGDINumInSystem(void)
{
int nGDINums = 0; /*所有进程的GDI对象之和*/
int nProcess = 0; /*系统中的进程数*/
为了回答这一问题,我们用Windows自带的任务管理器观察后发现,当程序界面开始混乱时,进程的GDI对象值为9999,那么为什么GDI对象达到9999后界面才发生混乱呢,带着这个疑问,我查找了一些资料,简单的了解到了Windows对GDI对象的管理方式。
GDI对象,实际上是Windows系统维护的一些数据结构。微软基于稳定性和健壮性考虑,将所有GDI对象的管理权都交给Windows系统的对象管理器管理,用户只能通过系统返回的“句柄”来操作这些对象。
在Windows 2000中,句柄实际上是一个DWORD类型的值。该DWORD值是一个32比特位的数据,它又分为两个部分:Table Index及Uniqueness Identifier,他们各占16位,因此,在理论上来说,Windows中的每个进程,所能访问的GDI对象的最大值是64K。然而,在Windows 2000中,客户句柄的最大数目被硬设置为16384 (16K);
然而,在Windows 2000中,既便客户句柄的最大数目被硬设置为16384,那么为什么在实际中GDI对象增加到9999后,程序界面就开始混乱了呢?原来,在Windows2000中,每进程的GDI对象的最大值又被默认为10000——据微软资料显示,之所以设置为10000,是为了阻止“Bad”程序分配过多的资源,因此,当GDI对象达到9999之后,程序就不能再创建新的GDI资源,这样,每次都使用新建资源来绘制界面的程序就产生混乱了。
不过,在Windows 2000及以后的操作系统中,每个进程可以创建的GDI对象的最大值,是可以通过修改注册表来重新设置的,在Windows 2000中,该注册表项所为:HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows下的"GDIProcessHandleQuota"。设置完新的值后,重启计算机后,系统中每进程可以使用的GDI对象数就会变成你新设置的数。
然而,上述说法并不完全正确!
据SYBASE的一份资料显示(http://www.sybase.com/detail?id=1019174),在Windwos2000中,只可以对”GDIProcessHandleQuota”值进行微调,如果设置的值超过15000,系统就变得不稳定。事实上,我在Windows 2000中进行了测试,当GetGuiResources函数的返回值为12288(12K)时,就已经不能创建新的GDI对象了,也就是说,在Windows 2000中当一个进程总的GDI对象数达到12288以后,就不能再创建新的GDI对象了。
那么,在Windows 2000中,进程所能创建的GDI对象数,是每个进程独立的,还是要受限于Windows操作系统呢?为此,我写了一个check程序,该程序批量创建指定数目的BRUSH对象,并统计本进程的GDI对象数及系统中总的GDI对象数,其运行界面如下(这里图显示不出来,不过无关紧要)
其中统计系统中总的GDI对象的代码如下:
int GetGDINumInSystem(void)
{
int nGDINums = 0; /*所有进程的GDI对象之和*/
int nProcess = 0; /*系统中的进程数*/
DWORD aProID[1024];
DWORD cbNeeded;
::EnumProcesses ( aProID, sizeof(aProID), &cbNeeded );
DWORD cbNeeded;
::EnumProcesses ( aProID, sizeof(aProID), &cbNeeded );
/*系统中进程总数*/
nProcess = cbNeeded / sizeof ( DWORD );
nProcess = cbNeeded / sizeof ( DWORD );
/*统计每个进程的GDI对象数*/
for ( INT i=0; i < nProcess; i ++ )
{
HANDLE hPro = ::OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProID[i] );
for ( INT i=0; i < nProcess; i ++ )
{
HANDLE hPro = ::OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProID[i] );
nGDINums += ::GetGuiResources ( hPro, GR_GDIOBJECTS );
CloseHandle ( hPro );
}
}
return nGDINums;
}
}
使用此check程序,做如下试验:
①修改Windows 2000的注册表项” GDIProcessHandleQuota”值为12000;
②开启一个check进程,在其中创建11000个GDI对象!
③开启第二个check进程(第一个进程不关闭),在其中创建11000个GDI对象。
试验结果表明,第一个进程的对象可以顺利创建,而第二个进程的对象则不能顺利创建,这就说明,在Windows 2000中,每个进程可以创建的GDI对象数,不仅在进程内部有一定限制,而且还受限于整个操作系统。经多次试验表明,当Windows 2000系统中总的GDI对象数达到15900以后的某个值后,进程就不能再创建GDI对象了,系统就变得不稳定了,至于该临界值到底是多少,各次试验结果并不一致,但是都在15900以后。
①修改Windows 2000的注册表项” GDIProcessHandleQuota”值为12000;
②开启一个check进程,在其中创建11000个GDI对象!
③开启第二个check进程(第一个进程不关闭),在其中创建11000个GDI对象。
试验结果表明,第一个进程的对象可以顺利创建,而第二个进程的对象则不能顺利创建,这就说明,在Windows 2000中,每个进程可以创建的GDI对象数,不仅在进程内部有一定限制,而且还受限于整个操作系统。经多次试验表明,当Windows 2000系统中总的GDI对象数达到15900以后的某个值后,进程就不能再创建GDI对象了,系统就变得不稳定了,至于该临界值到底是多少,各次试验结果并不一致,但是都在15900以后。
上面的测试是在Windows 2000中进行的,那么,在Windows 2003中,情况又是什么样呢?立即动手,到2003系统中,修改注册表项”GDIProcessHandleQuota”为20000,然后运行测试程序并在其中创建20000个GDI对象,一切正常! 再改,30000,运行,仍然正常;……直到改到了70000的时候,系统运行才会出现界面绘制问题,在这样的事实下,不得不做假设:难道Windows 2003中取消了客户GDI句柄最多16K的限制,而将限制设到了64K?
为了验证这个推测,我使用check程序直接创建64K的GDI资源,运行结果表明,当进程创建了一定的GDI对象之后,就不能创建新的GDI对象了,这表明上面的推测不完全正确,不过,基于在Windows 2000中的试验经验,很快就想到了在Windows 2003中系统可以创建的GDI对象应该还要受限于操作系统,也就是说:Windows 2003中放宽了每个进程可以创建的GDI对象数目,但是整个系统中GDI对象数不能超过某个值。为验证此结果,做如下试验:
①修改Windows 2003的注册表项” GDIProcessHandleQuota”值为50000;
②开启一个check进程,在其中创建40000个GDI对象!
③开启第二个check进程(第一个进程不关闭),在其中创建40000个GDI对象。
试验结果基本上和Windows 2000中的结果类似,唯一不同的是,在第二个进程创建GDI对象的过程中,当系统中总GDI对象达到63700以后的某个值后才会创建失败。同样,该临界值也不固定,不过多次试验表明,当总的GDI对象数达到63700以后,系统就变得不稳定了。
为了验证这个推测,我使用check程序直接创建64K的GDI资源,运行结果表明,当进程创建了一定的GDI对象之后,就不能创建新的GDI对象了,这表明上面的推测不完全正确,不过,基于在Windows 2000中的试验经验,很快就想到了在Windows 2003中系统可以创建的GDI对象应该还要受限于操作系统,也就是说:Windows 2003中放宽了每个进程可以创建的GDI对象数目,但是整个系统中GDI对象数不能超过某个值。为验证此结果,做如下试验:
①修改Windows 2003的注册表项” GDIProcessHandleQuota”值为50000;
②开启一个check进程,在其中创建40000个GDI对象!
③开启第二个check进程(第一个进程不关闭),在其中创建40000个GDI对象。
试验结果基本上和Windows 2000中的结果类似,唯一不同的是,在第二个进程创建GDI对象的过程中,当系统中总GDI对象达到63700以后的某个值后才会创建失败。同样,该临界值也不固定,不过多次试验表明,当总的GDI对象数达到63700以后,系统就变得不稳定了。
结论
经过上面的分析,我们可以知道,在Windows 2000/2003 操作系统中,每个进程可以创建的GDI对象,受限于三个方面因素:系统本身的两个方面的限制和Windows注册表中设置的最大值限制。
首先,每个进程可以创建的GDI对象数,在理论上为64K,但是在Windows 2000中,系统将客户可以创建的GDI句柄数硬设置为不能超过16K,而事实上当GDI对象数达到12K之后,系统即不正常;在Windows 2003中,系统放宽了对GDI对象数的限制,使得每个进程可以使用的GDI对象数接近64K;
其次,每个进程可以创建的GDI对象数,还受限于操作系统中GDI对象总数;在Windows 2000中,当系统中总的GDI对象达到15900以后的某个值后,进程就不能再创建新的GDI对象了;在20003中,这个值增加到63700以后的某个值。但是,到底是哪个值,则不固定。
最后,进程可创建的最大GDI对象数目还受限于注册表中HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows下的"GDIProcessHandleQuota" 项所设置的值,该值设置了Windows中每个进程可以创建的最大GDI对象数,在Windows 2000及2003系统中,其默认均为10000,这也就说明了当程序创建的GDI对象数达到9999之后界面为什么会混乱。
0 0
- WindowsNT中,GDI资源的管理
- GDI资源的释放
- GDI资源的释放
- GDI+的一些资源
- 程序中GDI资源占用与泄漏的初步分析
- WindowsNT下Service的编程
- WindowsNT 下的 Service 编程
- 从资源中读取图片 GDI+
- GDI+从资源中加载图片
- WTL中GDI+支持资源文件加载
- GDI+从资源文件中加载图片
- GDI 资源
- GDI对象猛增,GDI资源泄漏的问题
- C++类中资源的管理
- 关于GDI+的用法及资源下载
- 动态占用资源的gdi问题
- 软件运行中界面显示异常——GDI资源泄漏问题的排查过程
- WindowsNT/2000的系统日志文件
- Android TTS文字转语音开发
- 寒假之作—HDU—土地的侵蚀问题
- SELinux
- IOS开发-文件管理(二)
- 【SICP练习】3 练习1.7
- WindowsNT中,GDI资源的管理
- 学习PHP的过程记录(6)
- MyEclipse中部署安卓开发环境
- android读取短信获取验证码功能实现
- 安卓学习必备开发板-Rayeager PX2
- 第二十一篇 设计模式--中介模式
- tomcat 性能检测
- B. Fox And Two Dots
- 单片机ISP、IAP和ICP几种烧录方式的区别