There is still one more important limitation you've not considered. That is kernel mode paged pool.
Most of memory allocated for GDI objects are allocated from kernel mode, from kernel mode paged pool to be exact. There is a system-wide limitation of around 200 Mb for kernel mode paged pool, and 48 Mb per process.
Most of GDI objects are quite small, so this is not a problem. But there are two types of GDI objects which can be very large. They are DDB and GDI region.
使用此check程序,做如下试验:
① 修改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以后,系统就变得不稳定了。