Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> WindowsNT教程 >> WindowsNT資訊 >> Windows NT 中,系統資源如GDI資源是如何管理的?

Windows NT 中,系統資源如GDI資源是如何管理的?

日期:2017/2/10 11:07:04      編輯:WindowsNT資訊

#11樓 得分:0回復於:2006-04-29 08:37:18

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的一份資料顯示(?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   );

        /*系統中進程總數*/
        nProcess   =   cbNeeded   /   sizeof   (   DWORD   );

        /*統計每個進程的GDI對象數*/
        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中進行的,那麼,在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以後,系統就變得不穩定了。


結論
        經過上面的分析,我們可以知道,在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之後界面為什麼會混亂。

Copyright © Windows教程網 All Rights Reserved