日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

32位程序使用超过4G的内存 实例

發布時間:2023/12/29 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 32位程序使用超过4G的内存 实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ?最近在做個程序,雖然是小型程序,但是使用的內存量卻很大,動輒達到10G。在64位系統上可以輕松實現,無奈我是基于32位的系統進行開發,程序還沒跑起來就已經被終止了。??
??? 試過很多辦法,包括文件內存映射等,效率不高,而且由于32位應用程序的限制,可用的內存地址最高只能到0x7FFFFFFF,能調用的內存到2G就是極限了。最后好不容易找到了AWE(Address Windowing Extensions)。?
??? AWE是Windows的內存管理功能的一組擴展,它允許應用程序獲取物理內存,然后將非分頁內存的視圖動態映射到32位地址空間。雖然32位地址空間限制為4GB,但是非分頁內存卻可以遠遠大于4GB。這使需要大量內存的應用程序(如大型數據庫系統)能使用的內存量遠遠大于32位地址空間所支持的內存量。?
??? 與AWE有關的函數在后面介紹。?
??? 為了使用大容量內存,除了要用到AWE外,還有一樣東西不能少,那就是PAE(Physical Address Extension)。PAE是基于x86的服務器的一種功能,它使運行Windows Server 2003,Enterprise Edition 和Windows Server 2003,Datacenter Edition 的計算機可以支持 4 GB 以上物理內存。物理地址擴展(PAE)允許將最多64 GB的物理內存用作常規的4 KB頁面,并擴展內核能使用的位數以將物理內存地址從 32擴展到36。?
??? 一般情況下,windows系統的PAE沒有生效,只有開啟了PAE后windows系統才可以識別出4G以上的內存。在使用boot.int的系統中,要啟動PAE必須在boot.ini中加入/PAE選項。在Windows Vista和Windows7中則必須修改內核文件,同時設置BCD啟動項。針對Vista系統和Win7系統可以使用Ready For 4GB這個軟件直接完成這一操作,具體方法見Ready For 4GB的軟件說明。以下就是一個開啟了/PAE選項的boot.ini文件示例:

[xhtml]?view plaincopy
  • [boot?loader]??
  • timeout=30??
  • default=multi(0)disk(0)rdisk(0)partition(1)WINDOWS??
  • [operating?systems]??
  • multi(0)disk(0)rdisk(0)partition(1)WINDOWS="Windows?Server?2003,?Enterprise"?/fastdetect?/PAE??

  • ??? 本文將以Windows 7旗艦版為例介紹如何在打開PAE的情況下使用AWE在程序中達到使用2G以上內存的目的。下圖分別為開啟PAE和未開啟PAE時系統識別出的內存容量區別。?

    ?

    圖一.開啟PAE
    ?

    ?

    ?

    圖二.關閉PAE


    ??? 如果沒有打開PAE,系統只能認出3G的內存,最多可以再多0.5G不到,這樣即使使用AWE,由于系統和其他應用程序已經占去了一部分內存,剩下的內存或許也只有2G多一點了,沒什么太大提高。只有當系統認出了4G以上的內存,AWE才能發揮它真正的作用。

    ??? 下面我們看看windows中給出的有關AWE的API函數,它們都定義在winbase.h中。

    ?

    [cpp]?view plaincopy
  • #if?(_WIN32_WINNT?>=?0x0500)??
  • //??
  • //?Very?Large?Memory?API?Subset??
  • //??
  • ??
  • WINBASEAPI??
  • BOOL??
  • WINAPI??
  • AllocateUserPhysicalPages(??
  • ????__in????HANDLE?hProcess,??
  • ????__inout?PULONG_PTR?NumberOfPages,??
  • ????__out_ecount_part(*NumberOfPages,?*NumberOfPages)?PULONG_PTR?PageArray??
  • ????);??
  • ??
  • WINBASEAPI??
  • BOOL??
  • WINAPI??
  • FreeUserPhysicalPages(??
  • ????__in????HANDLE?hProcess,??
  • ????__inout?PULONG_PTR?NumberOfPages,??
  • ????__in_ecount(*NumberOfPages)?PULONG_PTR?PageArray??
  • ????);??
  • ??
  • WINBASEAPI??
  • BOOL??
  • WINAPI??
  • MapUserPhysicalPages(??
  • ????__in?PVOID?VirtualAddress,??
  • ????__in?ULONG_PTR?NumberOfPages,??
  • ????__in_ecount_opt(NumberOfPages)?PULONG_PTR?PageArray??
  • ????);??
  • //...??
  • #endif??
  • ?

    ??? 從winbase.h中的定義可以看出,只有當你的系統版本大于或等于0x0500時,才能夠使用AWE。各個版本的_WIN32_WINNT值見下表,Windows 2000以下的版本不能使用AWE。

    Minimum system required

    Minimum value for _WIN32_WINNT andWINVER

    Windows?7

    0x0601

    Windows Server?2008

    0x0600

    Windows?Vista

    0x0600

    Windows Server?2003 with SP1, Windows?XP with SP2

    0x0502

    Windows Server?2003, Windows?XP

    0x0501

    Windows?2000

    0x0500

    ??? 如果你的系統版本符合要求,但是編譯器在編譯加入了AWE API的代碼出錯,可以在程序頭文件中加入下面的代碼。

    [cpp]?view plaincopy
  • #ifndef?_WIN32_WINNT??
  • #define?_WIN32_WINNT?0x0501??
  • #endif????
  • ?

    ??? 下面簡要介紹一下每個API的功能。

    ?

    [cpp]?view plaincopy
  • BOOL?WINAPI?AllocateUserPhysicalPages(??//分配物理內存頁,用于后面AWE的內存映射??
  • ??__in?????HANDLE?hProcess,?????//指定可以使用此函數分配的內存頁的進程??
  • ??__inout??PULONG_PTR?NumberOfPages,????//分配的內存頁數,頁的大小由系統決定??
  • ??__out????PULONG_PTR?UserPfnArray??//指向存儲分配內存頁幀成員的數組的指針??
  • );??
  • ??
  • BOOL?WINAPI?FreeUserPhysicalPages(??//釋放AllocateUserPhysicalPages函數分配的內存??
  • ??__in?????HANDLE?hProcess,?????//釋放此進程虛擬地址空間中的分配的內存頁??
  • ??__inout??PULONG_PTR?NumberOfPages,????//要釋放的內存頁數??
  • ??__in?????PULONG_PTR?UserPfnArray??//指向存儲內存頁幀成員的數組的指針??
  • );??
  • ??
  • BOOL?WINAPI?MapUserPhysicalPages(???//將分配好的內存頁映射到指定的地址??
  • ??__in??PVOID?lpAddress,????????//指向要重映射的內存區域的指針??
  • ??__in??ULONG_PTR?NumberOfPages,????//要映射的內存頁數??
  • ??__in??PULONG_PTR?UserPfnArray?????//指向要映射的內存頁的指針??
  • );??
  • ?

    ??? 在看實例程序前還有一些設置需要做,需要對系統的本地安全策略進行設置。在win7中,打開“控制面板->系統和安全->管理工具->本地安全策略”,給“鎖定內存頁”添加當前用戶,然后退出,重啟(不重啟一般無法生效!)。

    ?

    ?

    ??? 經過前面的準備(再啰嗦一次:確認自己的電腦裝有4G或4G以上的內存;開啟PAE,使系統認出4G或以上的內存;設置好本地安全策略),我們就可以通過下面的代碼來做個實驗了。

    ?

    ??? 代碼是從MSDN中AWE的一個Example修改而來的,具體流程見代碼中的注釋,如果對該Example的源代碼有興趣可以參考MSDN。

    ?

    [cpp]?view plaincopy
  • #include?"AWE_TEST.h"??
  • #include?<windows.h>??
  • #include?<stdio.h>??
  • ??
  • #define?MEMORY_REQUESTED?((2*1024+512)*1024*1024)?//申請2.5G內存,測試機上只有4G內存,而且系統是window7,比較占內存.申請3G容易失敗.??
  • #define?MEMORY_VIRTUAL?1024*1024*512????????//申請長度0.5G的虛擬內存,即AWE窗口.??
  • ??
  • //檢測"鎖定內存頁"權限的函數??
  • BOOL?LoggedSetLockPagesPrivilege?(?HANDLE?hProcess,?BOOL?bEnable);??
  • ??
  • void?_cdecl?main()??
  • {??
  • ????BOOL?bResult;???????????????????//?通用bool變量??
  • ????ULONG_PTR?NumberOfPages;????????//?申請的內存頁數??
  • ????ULONG_PTR?NumberOfPagesInitial;?//?初始的要申請的內存頁數??
  • ????ULONG_PTR?*aPFNs;???????????????//?頁信息,存儲獲取的內存頁成員??
  • ????PVOID?lpMemReserved;????????????//?AWE窗口??
  • ????SYSTEM_INFO?sSysInfo;???????????//?系統信息??
  • ????INT?PFNArraySize;???????????????//?PFN隊列所占的內存長度??
  • ??
  • ????GetSystemInfo(&sSysInfo);??//?獲取系統信息??
  • ??
  • ????printf("This?computer?has?page?size?%d./n",?sSysInfo.dwPageSize);??
  • ??
  • ????//計算要申請的內存頁數.??
  • ??
  • ????NumberOfPages?=?MEMORY_REQUESTED/sSysInfo.dwPageSize;??
  • ????printf?("Requesting?%d?pages?of?memory./n",?NumberOfPages);??
  • ??
  • ????//?計算PFN隊列所占的內存長度??
  • ??
  • ????PFNArraySize?=?NumberOfPages?*?sizeof?(ULONG_PTR);??
  • ??
  • ????printf?("Requesting?a?PFN?array?of?%d?bytes./n",?PFNArraySize);??
  • ??
  • ????aPFNs?=?(ULONG_PTR?*)?HeapAlloc(GetProcessHeap(),?0,?PFNArraySize);??
  • ??
  • ????if?(aPFNs?==?NULL)???
  • ????{??
  • ????????printf?("Failed?to?allocate?on?heap./n");??
  • ????????return;??
  • ????}??
  • ??
  • ????//?開啟"鎖定內存頁"權限??
  • ??
  • ????if(?!?LoggedSetLockPagesPrivilege(?GetCurrentProcess(),?TRUE?)?)???
  • ????{??
  • ????????return;??
  • ????}??
  • ??
  • ????//?分配物理內存,長度2.5GB??
  • ??
  • ????NumberOfPagesInitial?=?NumberOfPages;??
  • ????bResult?=?AllocateUserPhysicalPages(?GetCurrentProcess(),??
  • ????????&NumberOfPages,??
  • ????????aPFNs?);??
  • ??
  • ????if(?bResult?!=?TRUE?)???
  • ????{??
  • ????????printf("Cannot?allocate?physical?pages?(%u)/n",?GetLastError()?);??
  • ????????return;??
  • ????}??
  • ??
  • ????if(?NumberOfPagesInitial?!=?NumberOfPages?)???
  • ????{??
  • ????????printf("Allocated?only?%p?pages./n",?NumberOfPages?);??
  • ????????return;??
  • ????}??
  • ??
  • ????//?保留長度0.5GB的虛擬內存塊(這個內存塊即AWE窗口)的地址??
  • ??
  • ????lpMemReserved?=?VirtualAlloc(?NULL,??
  • ????????MEMORY_VIRTUAL,??
  • ????????MEM_RESERVE?|?MEM_PHYSICAL,??
  • ????????PAGE_READWRITE?);??
  • ??
  • ????if(?lpMemReserved?==?NULL?)???
  • ????{??
  • ????????printf("Cannot?reserve?memory./n");??
  • ????????return;??
  • ????}??
  • ??
  • ????char?*strTemp;??
  • ????for?(int?i=0;i<5;i++)??
  • ????{??
  • ????????//?把物理內存映射到窗口中來??
  • ????????//?分5次映射,每次映射0.5G物理內存到窗口中來.??
  • ????????//?注意,在整個過程中,lpMenReserved的值都是不變的??
  • ????????//?但是映射的實際物理內存卻是不同的??
  • ????????//?這段代碼將申請的2.5G物理內存分5段依次映射到窗口中來??
  • ????????//?并在每段的開頭寫入一串字符串.??
  • ??
  • ????????bResult?=?MapUserPhysicalPages(?lpMemReserved,??
  • ????????????NumberOfPages/5,??
  • ????????????aPFNs+NumberOfPages/5*i);??
  • ??
  • ????????if(?bResult?!=?TRUE?)???
  • ????????{??
  • ????????????printf("MapUserPhysicalPages?failed?(%u)/n",?GetLastError()?);??
  • ????????????return;??
  • ????????}??
  • ??
  • ????????//?寫入字符串,雖然是寫入同一個虛存地址,??
  • ????????//?但是窗口映射的實際內存不同,所以是寫入了不同的內存塊中??
  • ????????strTemp=(char*)lpMemReserved;??
  • ????????sprintf(strTemp,"This?is?the?%dth?section!",i+1);??
  • ??
  • ????????//?解除映射??
  • ??
  • ????????bResult?=?MapUserPhysicalPages(?lpMemReserved,??
  • ????????????NumberOfPages/5,??
  • ????????????NULL?);??
  • ??
  • ????????if(?bResult?!=?TRUE?)???
  • ????????{??
  • ????????????printf("MapUserPhysicalPages?failed?(%u)/n",?GetLastError()?);??
  • ????????????return;??
  • ????????}??
  • ????}??
  • ??
  • ????//?現在再從5段內存中讀出剛才寫入的字符串??
  • ????for?(int?i=0;i<5;i++)??
  • ????{??
  • ????????//?把物理內存映射到窗口中來??
  • ??
  • ????????bResult?=?MapUserPhysicalPages(?lpMemReserved,??
  • ????????????NumberOfPages/5,??
  • ????????????aPFNs+NumberOfPages/5*i);??
  • ??
  • ????????if(?bResult?!=?TRUE?)???
  • ????????{??
  • ????????????printf("MapUserPhysicalPages?failed?(%u)/n",?GetLastError()?);??
  • ????????????return;??
  • ????????}??
  • ??
  • ????????//?將映射到窗口中的不同內存塊的字符串在屏幕中打印出來??
  • ????????strTemp=(char*)lpMemReserved;??
  • ????????printf("%s/n",strTemp);??
  • ??
  • ????????//?解除映射??
  • ??
  • ????????bResult?=?MapUserPhysicalPages(?lpMemReserved,??
  • ????????????NumberOfPages/5,??
  • ????????????NULL?);??
  • ??
  • ????????if(?bResult?!=?TRUE?)???
  • ????????{??
  • ????????????printf("MapUserPhysicalPages?failed?(%u)/n",?GetLastError()?);??
  • ????????????return;??
  • ????????}??
  • ????}??
  • ??????
  • ??
  • ????//?釋放物理內存空間??
  • ??
  • ????bResult?=?FreeUserPhysicalPages(?GetCurrentProcess(),??
  • ????????&NumberOfPages,??
  • ????????aPFNs?);??
  • ??
  • ????if(?bResult?!=?TRUE?)???
  • ????{??
  • ????????printf("Cannot?free?physical?pages,?error?%u./n",?GetLastError());??
  • ????????return;??
  • ????}??
  • ??
  • ????//?釋放虛擬內存地址??
  • ??
  • ????bResult?=?VirtualFree(?lpMemReserved,??
  • ????????0,??
  • ????????MEM_RELEASE?);??
  • ??
  • ????//?釋放PFN隊列空間??
  • ??
  • ????bResult?=?HeapFree(GetProcessHeap(),?0,?aPFNs);??
  • ??
  • ????if(?bResult?!=?TRUE?)??
  • ????{??
  • ????????printf("Call?to?HeapFree?has?failed?(%u)/n",?GetLastError()?);??
  • ????}??
  • ??
  • }??
  • ??
  • /*****************************************************************?
  • ?
  • 輸入:?
  • ?
  • HANDLE?hProcess:?需要獲得權限的進程的句柄?
  • ?
  • BOOL?bEnable:?啟用權限?(TRUE)?或?取消權限?(FALSE)??
  • ?
  • 返回值:?TRUE?表示權限操作成功,?FALSE?失敗.?
  • ?
  • *****************************************************************/??
  • BOOL??
  • LoggedSetLockPagesPrivilege?(?HANDLE?hProcess,??
  • ?????????????????????????????BOOL?bEnable)??
  • {??
  • ????struct?{??
  • ????????DWORD?Count;??
  • ????????LUID_AND_ATTRIBUTES?Privilege?[1];??
  • ????}?Info;??
  • ??
  • ????HANDLE?Token;??
  • ????BOOL?Result;??
  • ??
  • ????//?打開進程的安全信息??
  • ??
  • ????Result?=?OpenProcessToken?(?hProcess,??
  • ????????TOKEN_ADJUST_PRIVILEGES,??
  • ????????&?Token);??
  • ??
  • ????if(?Result?!=?TRUE?)???
  • ????{??
  • ????????printf(?"Cannot?open?process?token./n"?);??
  • ????????return?FALSE;??
  • ????}??
  • ??
  • ????//?開啟?或?取消???
  • ??
  • ????Info.Count?=?1;??
  • ????if(?bEnable?)???
  • ????{??
  • ????????Info.Privilege[0].Attributes?=?SE_PRIVILEGE_ENABLED;??
  • ????}???
  • ????else???
  • ????{??
  • ????????Info.Privilege[0].Attributes?=?0;??
  • ????}??
  • ??
  • ????//?獲得LUID??
  • ??
  • ????Result?=?LookupPrivilegeValue?(?NULL,??
  • ????????SE_LOCK_MEMORY_NAME,??
  • ????????&(Info.Privilege[0].Luid));??
  • ??
  • ????if(?Result?!=?TRUE?)???
  • ????{??
  • ????????printf(?"Cannot?get?privilege?for?%s./n",?SE_LOCK_MEMORY_NAME?);??
  • ????????return?FALSE;??
  • ????}??
  • ??
  • ????//?修改權限??
  • ??
  • ????Result?=?AdjustTokenPrivileges?(?Token,?FALSE,??
  • ????????(PTOKEN_PRIVILEGES)?&Info,??
  • ????????0,?NULL,?NULL);??
  • ??
  • ????//?檢查修改結果??
  • ??
  • ????if(?Result?!=?TRUE?)???
  • ????{??
  • ????????printf?("Cannot?adjust?token?privileges?(%u)/n",?GetLastError()?);??
  • ????????return?FALSE;??
  • ????}???
  • ????else???
  • ????{??
  • ????????if(?GetLastError()?!=?ERROR_SUCCESS?)???
  • ????????{??
  • ????????????printf?("Cannot?enable?the?SE_LOCK_MEMORY_NAME?privilege;?");??
  • ????????????printf?("please?check?the?local?policy./n");??
  • ????????????return?FALSE;??
  • ????????}??
  • ????}??
  • ??
  • ????CloseHandle(?Token?);??
  • ??
  • ????return?TRUE;??
  • }??
  • ?

    程序運行結果如下:

    ?

    ??? 可以看出系統分頁的大小為4K,總共申請了655360個分頁,也就是2.5G。每個分頁成員占4字節,總共2621440字節。2.5G內存分成5段512M的塊,成功寫入了字符串并成功讀取。

    ?

    ??? 在調試過程中,在執行了AllocateUserPhysicalPages函數后設置斷點,查看任務管理器,可以看出成功分配了物理內存后,實際物理內存被占用了2.5G,從而驗證了AWE的效果。

    ?

    ?

    ??? 通過上述示例,我們成功的在32位系統中識別出了4G的內存,并且在32位程序中成功使用了超過2G的內存。借助PAE和AWE,即使在32位系統上,我們也能夠順利開發對內存消耗較大的應用程序,而不需要依賴于64位平臺

    總結

    以上是生活随笔為你收集整理的32位程序使用超过4G的内存 实例的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美日韩一二 | 国产sss| 精品动漫3d一区二区三区免费版 | 嫩草嫩草嫩草嫩草嫩草 | 国产精品入口66mio男同 | 看免费的毛片 | 福利在线播放 | 欧美成人黄色小视频 | 狠狠干天天操 | 亚洲涩涩爱 | 日本免费电影一区二区三区 | 精品久久久久久久久久久久久久 | 貂蝉被到爽流白浆在线观看 | 亚洲免费网站在线观看 | 已婚少妇美妙人妻系列 | 一本视频 | 婷婷综合视频 | 日韩高清国产一区在线 | 色综合狠狠爱 | 成人免费毛片观看 | 亚洲精品国产欧美在线观看 | 东北少妇av | 中文av一区二区三区 | 色臀av| 成人漫画网站 | 成人短视频在线免费观看 | 日韩欧美精品在线观看 | 国产精品 欧美激情 | 久久久久久免费精品 | 午夜性色福利视频 | 青草在线视频 | 成人做爰黄| 欧美乱妇15p | 操一操| 嫩草天堂 | 毛片在线免费观看网址 | aa黄色大片 | 韩国伦理片在线播放 | 亚洲精品小视频 | 日韩电影中文字幕 | 婷婷色激情 | 可以看黄色的网站 | 色视频在线播放 | 亚洲va欧美va天堂v国产综合 | 天堂a√在线 | 日韩精品无码一区二区三区久久久 | 2023天天操 | 欧美有码在线 | www.一区二区三区 | 亚洲一区二区三区播放 | 少妇激情四射 | 亚洲欧美在线看 | 女女互慰吃奶互揉调教捆绑 | 五月激情在线 | 韩国91视频 | 婷婷六月天在线 | 中文字幕视频在线 | 精品少妇一区二区三区免费观看 | 日本国产中文字幕 | jzzijzzij日本成熟少妇 | 欧美极品三级 | 日韩理论片在线观看 | 成年人网站av| 免费日本在线 | 老子影院午夜伦不卡大全 | 波多野吉衣一区二区 | 久久久精品人妻一区二区三区四 | 国产97视频 | 伊人国产一区 | 一区二区三区伦理片 | 狠狠操狠狠爱 | 精品丰满少妇一区二区三区 | 97国产在线播放 | 久久久无码一区二区三区 | 久久久www成人免费毛片 | 免费看aaaaa级少淫片 | 夜色资源网| 日韩在线视屏 | 亚洲性生活 | 色多多视频在线 | 在线免费看污网站 | 久热这里有精品 | 蜜桃成人网 | 日本亚洲精品 | 欧美日韩不卡一区二区三区 | 天天操天天干天天操 | 国产高清区 | 国产一线二线三线女 | 国产高清在线观看视频 | 欧美不卡视频在线观看 | 精品在线小视频 | 伊人99在线 | 成年人的免费视频 | 激情亚洲天堂 | 97超碰免费观看 | 日韩色小说 | 呦女精品| 免费观看成年人网站 | 成年人av网站 |