




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、本文背景: 在編程中,很多Windows或C+的內(nèi)存函數(shù)不知道有什么區(qū)別,更別談?dòng)行褂?;根本?原因是,沒(méi)有清楚的理解操作系統(tǒng)的內(nèi)存管理機(jī)制,本文企圖通過(guò)簡(jiǎn)單的總結(jié)描述,結(jié)合實(shí) 例來(lái)闡明這個(gè)機(jī)制。本文目的:對(duì)Windows內(nèi)存管理機(jī)制了解清楚,有效的利用C+內(nèi)存函數(shù)管理和使用內(nèi)存。本文內(nèi)容:本文一共有六節(jié),由于篇幅較多,故按節(jié)發(fā)表。其他章節(jié)請(qǐng)看本人博客的Windows內(nèi)存管 理及C+內(nèi)存分配實(shí)例(二)(三)(四)(五)和(六)。1. 進(jìn)程地址空間1.1 地址空間32164位的系統(tǒng)ICPU操作系統(tǒng)運(yùn)行在硬件CPU 上, 32位操作系統(tǒng)運(yùn)行于32位CPU 上, 64位操作系統(tǒng) 運(yùn)行于 64 位
2、CPU 上;目前沒(méi)有真正的 64 位 CPU。32位CPU 一次只能操作32位二進(jìn)制數(shù);位數(shù)多CPU設(shè)計(jì)越復(fù)雜,軟件設(shè)計(jì)越簡(jiǎn)單。軟件的進(jìn)程運(yùn)行于32位系統(tǒng)上,其尋址位也是32 位,能表示的空間是232=4G,范 圍從 0 x0000 00000 xFFFF FFFF。NULL指針?lè)謪^(qū)范圍:0 x0000 00000 x0000 FFFF作用:保護(hù)內(nèi)存非法訪(fǎng)問(wèn)例子:分配內(nèi)存時(shí),如果由于某種原因分配不成功,則返回空指針0 x0000 0000 ;當(dāng)用戶(hù)繼 續(xù)使用比如改寫(xiě)數(shù)據(jù)時(shí),系統(tǒng)將因?yàn)榘l(fā)生訪(fǎng)問(wèn)違規(guī)而退出。那么,為什么需要那么大的區(qū)域呢,一個(gè)地址值不就行了嗎?我在想,是不是因?yàn)?不讓8或16位的程
3、序運(yùn)行于32位的系統(tǒng)上呢?!因?yàn)镹ULL分區(qū)剛好范圍是16的進(jìn)程空 間。獨(dú)享用戶(hù)分區(qū)范圍: 0 x0001 00000 x7FFE FFFF作用:進(jìn)程只能讀取或訪(fǎng)問(wèn)這個(gè)范圍的虛擬地址;超越這個(gè)范圍的行為都會(huì)產(chǎn)生違規(guī)退出例子:程序的二進(jìn)制代碼中所用的地址大部分將在這個(gè)范圍,所有exe和dll文件都加載 到這個(gè)。每個(gè)進(jìn)程將近2G的空間是獨(dú)享的。注意:如果在boot.ini上設(shè)置了/3G,這個(gè)區(qū)域的范圍從2G擴(kuò)大為3G: 0 x0001 0000OxBFFE FFFF。共享內(nèi)核分區(qū)范圍: 0 x8000 00000 xFFFF FFFF作用:這個(gè)空間是供操作系統(tǒng)內(nèi)核代碼、設(shè)備驅(qū)動(dòng)程序、設(shè)備I/O高速
4、緩存、非頁(yè)面內(nèi)存池 的分配、進(jìn)程目表和頁(yè)表等。例子:這段地址各進(jìn)程是可以共享的。注意:如果在boot.ini上設(shè)置了/3G,這個(gè)區(qū)域的范圍從2G縮小為1G: 0 xC000 00000 xFFFF FFFF。通過(guò)以上分析,可以知道,如果系統(tǒng)有n個(gè)進(jìn)程,它所需的虛擬空間是:2G*n+2G (內(nèi) 核只需2G的共享空間)。1 .2地址映射區(qū)域區(qū)域指的是上述地址空間中的一片連續(xù)地址。區(qū)域的大小必須是粒度64k)的整數(shù)倍,不是 的話(huà)系統(tǒng)自動(dòng)處理成整數(shù)倍。不同CPU粒度大小是不一樣的,大部分都是64K。區(qū)域的狀態(tài)有:空閑、私有、映射、映像。在你的應(yīng)用程序中,申請(qǐng)空間的過(guò)程稱(chēng)作保留f預(yù)訂),可以用Virtu
5、alAlloc;刪除空間的過(guò)程 為釋放,可以用 VirtualFree。在程序里預(yù)訂了地址空間以后,你還不可以存取數(shù)據(jù),因?yàn)槟氵€沒(méi)有付錢(qián),沒(méi)有真 實(shí)的 RAM 和它關(guān)聯(lián)。這時(shí)候的區(qū)域狀態(tài)是私有;默認(rèn)情況下,區(qū)域狀態(tài)是空閑;當(dāng)exe或DLL文件被映射進(jìn)了進(jìn)程空間后,區(qū)域狀態(tài)變成映像;當(dāng)一般數(shù)據(jù)文件被映射進(jìn)了進(jìn)程空間后,區(qū)域狀態(tài)變成映射。物理存儲(chǔ)器Windows各系列支持的內(nèi)存上限是不一樣的,從2G到64G不等。理論上32位CPU,硬件 上只能支持4G內(nèi)存的尋址;能支持超過(guò)4G的內(nèi)存只能靠其他技術(shù)來(lái)彌補(bǔ)。順便提一下,Windows個(gè)人版只能支持最大2G內(nèi)存,Intel使用Address Windo
6、ws Extension (AWE)技術(shù) 使得尋址范圍為236=64G。當(dāng)然,也得操作系統(tǒng)配合。內(nèi)存分配的最小單位是4K或8K, 般來(lái)說(shuō),根據(jù)CPU不同而不同,后面你可以 看到可以通過(guò)系統(tǒng)函數(shù)得到區(qū)域粒度和頁(yè)面粒度。頁(yè)文件頁(yè)文件是存在硬盤(pán)上的系統(tǒng)文件,它的大小可以在系統(tǒng)屬性里面設(shè)置,它相當(dāng)于物理內(nèi)存 所以稱(chēng)為虛擬內(nèi)存。事實(shí)上,它的大小是影響系統(tǒng)快慢的關(guān)鍵所在,如果物理內(nèi)存不多的情 況下。每頁(yè)的大小和上述所說(shuō)內(nèi)存分配的最小單位是一樣的,通常是4K或8K。訪(fǎng)問(wèn)屬性物理頁(yè)面的訪(fǎng)問(wèn)屬性指的是對(duì)頁(yè)面進(jìn)行的具體操作:可讀、可寫(xiě)、可執(zhí)行。 CPU 一般不支 持可執(zhí)行,它認(rèn)為可讀就是可執(zhí)行。但是,操作系統(tǒng)提供
7、這個(gè)可執(zhí)行的權(quán)限。PAGE_NOACCESSPAGE_READONLYPAGE_READWRITEPAGE_EXECUTEPAGE_EXECUTE_READPAGE_EXECUTE_READWRITE這6 個(gè)屬性很好理解,第一個(gè)是拒絕所有操作,最后一個(gè)是接受收有操作;PAGE_WRITECOPYPAGE_EXECUTE_WRITECOPY這兩個(gè)屬性在運(yùn)行同一個(gè)程序的多個(gè)實(shí)例時(shí)非常有用;它使得程序可以共享代碼段和數(shù)據(jù) 段。一般情況下,多個(gè)進(jìn)程只讀或執(zhí)行頁(yè)面,如果要寫(xiě)的話(huà),將會(huì)Copy頁(yè)面到新的頁(yè)面。 通過(guò)映射exe文件時(shí)設(shè)置這兩個(gè)屬性可以達(dá)到這個(gè)目的。PAGE_NOCACHEPAGE_WRITE
8、COMBINE這兩個(gè)是開(kāi)發(fā)設(shè)備驅(qū)動(dòng)的時(shí)候需要的。PAGE_GUARD當(dāng)往頁(yè)面寫(xiě)入一個(gè)字節(jié)時(shí),應(yīng)用程序會(huì)收到堆棧溢出通知,在線(xiàn)程堆棧時(shí)有用。映射過(guò)程進(jìn)程地址空間的地址是虛擬地址,也就是說(shuō),當(dāng)取到指令時(shí),需要把虛擬地址轉(zhuǎn)化為物理地 址才能夠存取數(shù)據(jù)。這個(gè)工作通過(guò)頁(yè)目和頁(yè)表進(jìn)行。從圖中可以看出,頁(yè)目大小為4K,其中每一項(xiàng)(32位)保存一個(gè)頁(yè)表的物理地址;每個(gè)頁(yè)表 大小為4K,其中每一項(xiàng)(32位)保存一個(gè)物理頁(yè)的物理地址,一共有1024個(gè)頁(yè)表。利用這 4K+4K*1K=4.4M的空間可以表示進(jìn)程的1024*1024* (頁(yè)4K) =4G的地址空間。進(jìn)程空間中的32位地址如下:高10位用來(lái)找到1024個(gè)
9、頁(yè)目項(xiàng)中的一項(xiàng),取出頁(yè)表的物理地址后,利用中10位來(lái)得到頁(yè) 表項(xiàng)的值,根據(jù)這個(gè)值得到物理頁(yè)的地址,由于一頁(yè)有4K大小,利用低12位得到單元地 址,這樣就可以訪(fǎng)問(wèn)這個(gè)內(nèi)存單元了。每個(gè)進(jìn)程都有自己的一個(gè)頁(yè)目和頁(yè)表,那么,剛開(kāi)始進(jìn)程是怎么找到頁(yè)目所在的物 理頁(yè)呢?答案是CPU的CR3寄存器會(huì)保存當(dāng)前進(jìn)程的頁(yè)目物理地址。當(dāng)進(jìn)程被創(chuàng)建時(shí),同時(shí)需要?jiǎng)?chuàng)建頁(yè)目和頁(yè)表,一共需要4.4M。在進(jìn)程的空間中,0 xC030 00000 xC030 0FFF是用來(lái)保存頁(yè)目的4k空間。0 xC000 00000 xC03F FFFF是用來(lái) 保存頁(yè)表的4M空間。也就是說(shuō)程序里面訪(fǎng)問(wèn)這些地址你是可以讀取頁(yè)目和頁(yè)表的具體值的
10、(要工作在內(nèi)核方式下)。有一點(diǎn)我不明白的是,頁(yè)表的空間包含了頁(yè)目的空間!至于說(shuō),頁(yè)目和頁(yè)表是保存在物理內(nèi)存還是頁(yè)文件中,我覺(jué)得,頁(yè)目比較常用,應(yīng) 該在物理內(nèi)存的概率大點(diǎn),頁(yè)表需要時(shí)再?gòu)捻?yè)文件導(dǎo)入物理內(nèi)存中。頁(yè)目項(xiàng)和頁(yè)表項(xiàng)是一個(gè)32位的值,當(dāng)頁(yè)目項(xiàng)第0位為1時(shí),表明頁(yè)表已經(jīng)在物理 內(nèi)存中;當(dāng)頁(yè)表項(xiàng)第0位為1時(shí),表明訪(fǎng)問(wèn)的數(shù)據(jù)已經(jīng)在內(nèi)存中。還有很多數(shù)據(jù)是否已經(jīng)被 改變,是否可讀寫(xiě)等標(biāo)志。另外,當(dāng)頁(yè)目項(xiàng)第7位為1時(shí),表明這是一個(gè)4M的頁(yè)面,這值 已經(jīng)是物理頁(yè)地址,用虛擬地址的低22位作為偏移量。還有很多:數(shù)據(jù)是否已經(jīng)被改變、 是否可讀寫(xiě)等標(biāo)志。1.3 一個(gè)例子編寫(xiě)生成軟件程序exe軟件描述如下:Ma
11、in ()1 :定義全局變量2:處理函數(shù)邏輯(Load所需DLL庫(kù),調(diào)用方法處理邏輯)3:定義并實(shí)現(xiàn)各種方法(方法含有局部變量)4:程序結(jié)束將程序編譯,生成exe文件,附帶所需的DLL庫(kù)。exe 文件格式 exe文件有自己的格式,有若干節(jié)(section): .text用來(lái)放二進(jìn)制代碼(exe或dll); .data用 來(lái)放各種全局?jǐn)?shù)據(jù)。.text指令 1: move a, b指令 2: add a, b.data數(shù)據(jù) 1: a=2數(shù)據(jù) 2: b=1這些地址都是虛擬地址,也就是進(jìn)程的地址空間。運(yùn)行exe程序建立進(jìn)程:運(yùn)行這個(gè)exe程序時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)進(jìn)程,建立進(jìn)程控制塊PCB,生成進(jìn)程頁(yè) 目
12、和頁(yè)表,放到PCB中。數(shù)據(jù)對(duì)齊:數(shù)據(jù)的內(nèi)存地址除以數(shù)據(jù)的大小,余數(shù)為0 時(shí)說(shuō)明數(shù)據(jù)是對(duì)齊的?,F(xiàn)在的編譯器 編譯時(shí)就考慮數(shù)據(jù)對(duì)齊的問(wèn)題,生成 exe 文件后,數(shù)據(jù)基本上是對(duì)齊的, CPU 運(yùn)行時(shí),寄 存器有標(biāo)志標(biāo)識(shí)CPU是否能夠自動(dòng)對(duì)齊數(shù)據(jù),如果遇到不能對(duì)齊的情況,或者通過(guò)兩次訪(fǎng) 問(wèn)內(nèi)存,或者通知操作系統(tǒng)處理。要注意的是,如果數(shù)據(jù)沒(méi)有對(duì)齊,CPU處理的效率是很低的。文件映射:系統(tǒng)不會(huì)將整個(gè) exe 文件和所有的 DLL 文件裝載進(jìn)物理內(nèi)存中,同時(shí)它也不會(huì) 裝載進(jìn)頁(yè)面文件中。相反,它會(huì)建立文件映射,也就是利用exe本身當(dāng)作頁(yè)面文件。系統(tǒng)將 部分二進(jìn)制代碼裝載進(jìn)內(nèi)存,分配頁(yè)面給它。假設(shè)分配了一個(gè)頁(yè)面
13、,物理地址為0 x0232 FFF1。其中裝載的一個(gè)指令虛擬地址為 0 x4000 1001=0100 0000 00 0000 0000 01 0000 0000 0001。一個(gè)頁(yè)面有 4K,系統(tǒng)會(huì)將指令保 存在低12位0 x0001的地址處。同時(shí),系統(tǒng)根據(jù)高10位0 x0100找到頁(yè)目項(xiàng),如果沒(méi)有關(guān)聯(lián) 的頁(yè)表,系統(tǒng)會(huì)生成一個(gè)頁(yè)表,分配一個(gè)物理頁(yè);然后,根據(jù)中10位 0 x0001 找到表項(xiàng),將 物理地址 0 x0232 FFF1 存進(jìn)去。執(zhí)行過(guò)程:執(zhí)行時(shí),當(dāng)系統(tǒng)拿到一個(gè)虛擬地址,就根據(jù)頁(yè)目和頁(yè)表找到數(shù)據(jù)的地址,根據(jù)頁(yè)目上的值可 以判斷頁(yè)表是在頁(yè)文件中還是在內(nèi)存中;如果在頁(yè)文件中,會(huì)將頁(yè)面導(dǎo)
14、入內(nèi)存,更新頁(yè)目項(xiàng)。讀取頁(yè)表項(xiàng)的值后,可以判斷數(shù)據(jù)頁(yè)文 件中還是在物理內(nèi)存中;如果在頁(yè)文件中,會(huì)導(dǎo)入到內(nèi)存中,更新頁(yè)表項(xiàng)。最終,拿到了數(shù) 據(jù)。在分配物理頁(yè)的過(guò)程中,系統(tǒng)會(huì)根據(jù)內(nèi)存分配的狀況適當(dāng)淘汰暫時(shí)不用的頁(yè)面,如果頁(yè) 面內(nèi)容改變了(通過(guò)頁(yè)表項(xiàng)的標(biāo)志位),保存到頁(yè)文件中,系統(tǒng)會(huì)維護(hù)內(nèi)存與頁(yè)文件的對(duì)應(yīng) 關(guān)系。由于將 exe 文件當(dāng)作內(nèi)存映射文件,當(dāng)需要改變數(shù)據(jù),如更改全局變量的值時(shí),利用Copy-On-Write的機(jī)制,重新生成頁(yè)文件,將結(jié)果保存在這個(gè)頁(yè)文件中,原來(lái)的頁(yè)文件還是 需要被其他進(jìn)程實(shí)例使用的。在清楚了指令和數(shù)據(jù)是如何導(dǎo)入內(nèi)存,如何找到它們的情況下,剩下的就是CPU不斷 的取指令、運(yùn)行
15、、保存數(shù)據(jù)的過(guò)程了,當(dāng)進(jìn)程結(jié)束后,系統(tǒng)會(huì)清空之前的各種結(jié)構(gòu)、釋放相 關(guān)的物理內(nèi)存和刪除頁(yè)文件。本文背景: 在編程中,很多Windows或C+的內(nèi)存函數(shù)不知道有什么區(qū)別,更別談?dòng)行褂茫桓镜?原因是,沒(méi)有清楚的理解操作系統(tǒng)的內(nèi)存管理機(jī)制,本文企圖通過(guò)簡(jiǎn)單的總結(jié)描述,結(jié)合實(shí) 例來(lái)闡明這個(gè)機(jī)制。本文目的:對(duì)Windows內(nèi)存管理機(jī)制了解清楚,有效的利用C+內(nèi)存函數(shù)管理和使用內(nèi)存。本文內(nèi)容:本文一共有六節(jié),由于篇幅較多,故按節(jié)發(fā)表。其他章節(jié)請(qǐng)看本人博客的Windows內(nèi)存管 理及C+內(nèi)存分配實(shí)例(一)(三)(四)(五)和(六)。2. 內(nèi)存狀態(tài)查詢(xún)函數(shù)系統(tǒng)信息Windows 提供 API 可以查詢(xún)系統(tǒng)
16、內(nèi)存的一些屬性,有時(shí)候我們需要獲取一些頁(yè)面大小、分 配粒度等屬性,在分配內(nèi)存時(shí)用的上。請(qǐng)看以下C+程序:SYSTEM_INFO sysInfo;GetSystemInfo(&sysInfo);coutvv機(jī)器屬性:vvendl;coutvv頁(yè)大小=vvsysInfo.dwPageSizevvendl;coutvv分配粒度=vvsysInfo.dwAllocationGranularityvvendl;coutv 用戶(hù)區(qū)最小值=vvsysInfo.lpMinimumApplicationAddressvvendl;coutvv用戶(hù)區(qū)最大值=vvsysInfo.lpMaximumApplicati
17、onAddressvvendlvvendl;結(jié)果如下:可以看出,頁(yè)面大小是4K,區(qū)域分配粒度是64K,進(jìn)程用戶(hù)區(qū)是0 x0001 00000 x7FFE FFFF。內(nèi)存狀態(tài)內(nèi)存狀態(tài)可以獲取總內(nèi)存和可用內(nèi)存,包括頁(yè)文件和物理內(nèi)存。請(qǐng)看以下C+程序:MEMORYSTATUS memStatus;GlobalMemoryStatus(&memStatus);coutvv內(nèi)存初始狀態(tài):vvendl;coutvv內(nèi)存繁忙程度=vvmemStatus.dwMemoryLoadvvendl;coutvv總物理內(nèi)存=vvmemStatus.dwTotalPhysvvendl;coutvv可用物理內(nèi)存=vvme
18、mStatus.dwAvailPhysvvendl;coutvv總頁(yè)文件=vvmemStatus.dwTotalPageFilevvendl;coutvv可用頁(yè)文件=vvmemStatus.dwAvailPageFilevvendl;coutvv總進(jìn)程空間=vvmemStatus.dwTotalVirtualvvendl;coutvv可用進(jìn)程空間=vvmemStatus.dwAvailVirtualvvendlvvendl;結(jié)果如下:可以看出,總物理內(nèi)存是1G,可用物理內(nèi)存是510兆,總頁(yè)文件是2.5G,這個(gè)是包含物理 內(nèi)存的頁(yè)文件;可用頁(yè)文件是1.9G。這里還標(biāo)識(shí)了總進(jìn)程空間,還有可用的進(jìn)程
19、空間,程序 只用了22兆的內(nèi)存空間。這里說(shuō)的都是大約數(shù)。內(nèi)存繁忙程序是標(biāo)識(shí)當(dāng)前系統(tǒng)內(nèi)存管理的繁忙程序,從0到100,其實(shí)用處不大。在函數(shù)里面靜態(tài)分配一些內(nèi)存后,看看究竟發(fā)生什么char stat65536;MEMORYSTATUS memStatus1;GlobalMemoryStatus(&memStatus1);coutvv靜態(tài)分配空間:vvendl;printf(指針地址=%xn,stat);coutvv減少物理內(nèi)存=vvmemStatus.dwAvailPhys-memStatus1.dwAvailPhysvvendl;coutvv減少可用頁(yè)文件=vvmemStatus.dwAvail
20、PageFile-memStatus1.dwAvailPageFilevvendl;coutvv減少可用進(jìn)程空間=vvmemStatus.dwAvailVirtual- memSta tus1.dwAvailVirtualendlendl;結(jié)果如下:可以看出,物理內(nèi)存、可用頁(yè)文件和進(jìn)程空間都沒(méi)有損耗。因?yàn)榫植孔兞渴欠峙湓诰€(xiàn)程堆棧 里面的,每個(gè)線(xiàn)程系統(tǒng)都會(huì)建立一個(gè)默認(rèn)1M大小的堆棧給線(xiàn)程函數(shù)調(diào)用使用。如果分配超 過(guò)1M,就會(huì)出現(xiàn)堆棧溢出。在函數(shù)里面動(dòng)態(tài)分配300M的內(nèi)存后,看看究竟發(fā)生什么char *dynamic=new char300*1024*1024;MEMORYSTATUS memSt
21、atus2;GlobalMemoryStatus(&memStatus2);coutvv動(dòng)態(tài)分配空間:vvendl;printf(指針地址=%xn,dynamic);coutvv減少物理內(nèi)存=vvmemStatus.dwAvailPhys-memStatus2.dwAvailPhysvvendl;coutvv減少可用頁(yè)文件=vvmemStatus.dwAvailPageFile-memStatus2.dwAvailPageFilevvendl;coutvv減少可用進(jìn)程空間=vvmemStatus.dwAvailVirtual-memStatus2.dwAvailVirtualvvendlvve
22、ndl;結(jié)果如下:動(dòng)態(tài)分配情況下,系統(tǒng)分配直到內(nèi)存頁(yè)文件使用完為止,當(dāng)然,系統(tǒng)要留一下系統(tǒng)使用的頁(yè) 面。進(jìn)程區(qū)域地址查詢(xún)?cè)诮o定一個(gè)進(jìn)程空間的地址后,可以查詢(xún)它所在區(qū)域和相鄰頁(yè)面的狀態(tài),包括頁(yè)面保護(hù)屬性、 存儲(chǔ)器類(lèi)型等。C+靜態(tài)分配了兩次內(nèi)存,一次是4K大一點(diǎn),一個(gè)是900K左右。char arrayA4097;char arrayB900000;第一次查詢(xún):long len=sizeof(MEMORY_BASIC_INFORMATION);MEMORY_BASIC_INFORMATION mbiA;VirtualQuery(arrayA,&mbiA,len);coutvv靜態(tài)內(nèi)存地址屬性:vv
23、endl;coutvv區(qū)域基地址=vvmbiA.AllocationBasevvendl;coutvv區(qū)域鄰近頁(yè)面狀態(tài)vvmbiA.Statevvendl;coutvv區(qū)域保護(hù)屬性=vvmbiA.AllocationProtectvvendl;coutvv頁(yè)面基地址=vvmbiA.BaseAddressvvendl; printf(arrayA 指針地址=%xn,arrayA);coutvv從頁(yè)面基地址開(kāi)始的大小vvmbiA.RegionSizevvendl;coutvv鄰近頁(yè)面物理存儲(chǔ)器類(lèi)型=vvmbiA.Typevvendl;coutvv頁(yè)面保護(hù)屬性=vvmbiA.Protectvvend
24、lvvendl;第二次查詢(xún):MEMORY_BASIC_INFORMATION mbiB;VirtualQuery(arrayB,&mbiB,len);coutvv靜態(tài)內(nèi)存地址屬性:vvendl;coutvv區(qū)域基地址=vvmbiB.AllocationBasevvendl;coutvv區(qū)域鄰近頁(yè)面狀態(tài)vvmbiB.Statevvendl;coutvv區(qū)域保護(hù)屬性=vvmbiB.AllocationProtectvvendl;coutvv頁(yè)面基地址=vvmbiB.BaseAddressvvendl;printf(arrayB 指針地址=%xn,arrayB);coutvv從頁(yè)面基地址開(kāi)始的大小、
25、=vvmbiB.RegionSizevvendl;coutvv鄰近頁(yè)面物理存儲(chǔ)器類(lèi)型=vvmbiB.Typevvendl;說(shuō)明:區(qū)域基地址指的是給定地址所在的進(jìn)程空間區(qū)域;鄰近頁(yè)面狀態(tài)指的是與給定地址所在頁(yè)面狀態(tài)相同頁(yè)面的屬性:MEM_FREE(空閑=65536)、 MEM_RESERVE (保留=8192)和 MEM_COMMIT (提交=4096)。區(qū)域保護(hù)屬性指的是區(qū)域初次被保留時(shí)被賦予的保護(hù)屬性:PAGE_READONLY(2)、PAGE_READWRITE(4)PAGE_WRITECOPY(8)和 PAGE_EXECUTE_WRITECOPY( 128) 等等。頁(yè)面基地址指的是給定地
26、址所在頁(yè)面的基地址。從頁(yè)面基地址開(kāi)始的區(qū)域頁(yè)面的大小,指的是與給定地址所在頁(yè)面狀態(tài)、保護(hù)屬性相同的頁(yè) 面。鄰近頁(yè)面物理存儲(chǔ)器類(lèi)型指的是與給定地址所在頁(yè)面相同的存儲(chǔ)器類(lèi)型,包括:MEM_PRIVATE (頁(yè)文件=131072)、MEM_MAPPED (文件映射=262144)和 MEM_IMAGE (exe 映像=16777216)。頁(yè)面保護(hù)屬性指的是頁(yè)面被指定的保護(hù)屬性,在區(qū)域保護(hù)屬性指定后更新。結(jié)果如下:如前所說(shuō),這是在堆棧區(qū)域0 x0004 0000里分配的,后分配的地址arrayB反而更小,符合堆 棧的特性。 arrayA 和 arrayB 它們處于不同的頁(yè)面。頁(yè)面都受頁(yè)文件支持,并且區(qū)
27、域都是提 交的,是系統(tǒng)在線(xiàn)程創(chuàng)建時(shí)提交的。C+動(dòng)態(tài)分配了兩次內(nèi)存,一次是1K大一點(diǎn),一個(gè)是64K左右。所以應(yīng)該不會(huì)在一個(gè)區(qū)域。char *dynamicA=new char1024;char *dynamicB=new char65467;VirtualQuery(dynamicA,&mbiA,len);coutvv動(dòng)態(tài)內(nèi)存地址屬性:vvendl;coutvv區(qū)域基地址=vvmbiA.AllocationBasevvendl;coutvv區(qū)域鄰近頁(yè)面狀態(tài)vvmbiA.Statevvendl;coutvv區(qū)域保護(hù)屬性=vvmbiA.AllocationProtectvvendl;printf(d
28、ynamicA 指針地址=%xn,dynamicA);coutvv從頁(yè)面基地址開(kāi)始的大小vvmbiA.RegionSizevvendl;coutvv鄰近頁(yè)面物理存儲(chǔ)器類(lèi)型=vvmbiA.Typevvendl;coutvv頁(yè)面保護(hù)屬性=vvmbiA.Protectvvendlvvendl;VirtualQuery(dynamicB,&mbiB,len);coutvv動(dòng)態(tài)內(nèi)存地址屬性:vvendl;coutvv區(qū)域基地址=vvmbiB.AllocationBasevvendl;coutvv區(qū)域鄰近頁(yè)面狀態(tài)vvmbiB.Statevvendl;coutvv區(qū)域保護(hù)屬性=vvmbiB.Allocati
29、onProtectvvendl;coutvv頁(yè)面基地址=vvmbiB.BaseAddressvvendl;printf(dynamicB 指針地址=%xn,dynamicB);coutvv從頁(yè)面基地址開(kāi)始的大小、=vvmbiB.RegionSizevvendl;coutvv鄰近頁(yè)面物理存儲(chǔ)器類(lèi)型=vvmbiB.Typevvendl;coutvv頁(yè)面保護(hù)屬性=vvmbiB.Protectvvendl;結(jié)果如下:這里是動(dòng)態(tài)分配,dynamicA和dynamicB處于兩個(gè)不同的區(qū)域;同樣,頁(yè)面都受頁(yè)文件支持, 并且區(qū)域都是提交的。第二個(gè)區(qū)域是比64K大的,由分配粒度可知,區(qū)域至少是128K。那么,剩
30、下的空間也是提 交的嗎,如果是的話(huà)那就太浪費(fèi)了。看看就知道了: 0 x00E2 1000肯定在這個(gè)空間里,所以 查詢(xún)?nèi)缦拢篤irtualQuery(char*)0 xE23390,&mbiB,len);coutvv動(dòng)態(tài)內(nèi)存地址屬性:vvendl;coutvv區(qū)域基地址=vvmbiB.AllocationBasevvendl;coutvv區(qū)域鄰近頁(yè)面狀態(tài)vvmbiB.Statevvendl;coutvv頁(yè)面基地址=vvmbiB.BaseAddressvvendl;printf(dynamicB 指針地址=%xn,0 xE21000);coutvv從頁(yè)面基地址開(kāi)始的大小vvmbiB.RegionS
31、izevvendl;coutvv鄰近頁(yè)面物理存儲(chǔ)器類(lèi)型=vvmbiB.Typevvendl;coutvv頁(yè)面保護(hù)屬性=vvmbiB.Protectvvendl;結(jié)果如下:可以看出,鄰近頁(yè)面狀態(tài)為保留,還沒(méi)提交,預(yù)料之中;0 x00E1 0000這個(gè)區(qū)域的大小可以 計(jì)算出來(lái):69632+978944=1024K。系統(tǒng)動(dòng)態(tài)分配了 1M的空間,就為了 64K左右大小的空 間??赡苁菫榱耸沟孟麓斡幸蠓峙鋾r(shí)時(shí)不用再分配了。本 文 來(lái) 自 CSDN 博 客 , 轉(zhuǎn) 載 請(qǐng) 標(biāo) 明 出 處 HYPERLINK /yeming81/archive/2008/01/16/2046207.aspx /yemin
32、g81/archive/2008/01/16/2046207.aspx本文背景: 在編程中,很多Windows或C+的內(nèi)存函數(shù)不知道有什么區(qū)別,更別談?dòng)行褂?;根本?原因是,沒(méi)有清楚的理解操作系統(tǒng)的內(nèi)存管理機(jī)制,本文企圖通過(guò)簡(jiǎn)單的總結(jié)描述,結(jié)合實(shí) 例來(lái)闡明這個(gè)機(jī)制。本文目的:對(duì)Windows內(nèi)存管理機(jī)制了解清楚,有效的利用C+內(nèi)存函數(shù)管理和使用內(nèi)存。本文內(nèi)容:本文一共有六節(jié),由于篇幅較多,故按節(jié)發(fā)表。其他章節(jié)請(qǐng)看本人博客的Windows內(nèi)存管 理及C+內(nèi)存分配實(shí)例(一)(二)(四)(五)和(六)。3.內(nèi)存管理機(jī)制-虛擬內(nèi)存 (VM)虛擬內(nèi)存使用場(chǎng)合虛擬內(nèi)存最適合用來(lái)管理大型對(duì)象或數(shù)據(jù)結(jié)構(gòu)。比
33、如說(shuō),電子表格程序,有很多單元格,但 是也許大多數(shù)的單元格是沒(méi)有數(shù)據(jù)的,用不著分配空間。也許,你會(huì)想到用動(dòng)態(tài)鏈表,但是 訪(fǎng)問(wèn)又沒(méi)有數(shù)組快。定義二維數(shù)組,就會(huì)浪費(fèi)很多空間。它的優(yōu)點(diǎn)是同時(shí)具有數(shù)組的快速和鏈表的小空間的優(yōu)點(diǎn)。分配虛擬內(nèi)存如果你程序需要大塊內(nèi)存,你可以先保留內(nèi)存,需要的時(shí)候再提交物理存儲(chǔ)器。在需要的時(shí)候再提交才能有效的利用內(nèi)存。一般來(lái)說(shuō),如果需要內(nèi)存大于1M,用虛擬內(nèi)存比較好。 保留用以下 Windows 函數(shù)保留內(nèi)存塊VirtualAlloc (PVOID 開(kāi)始地址, SIZE_T 大小, DWORD 類(lèi)型, DWORD 保護(hù)屬性)一般情況下,你不需要指定“開(kāi)始地址”,因?yàn)槟悴恢?/p>
34、進(jìn)程的那段空間是不是已經(jīng)被占用 了;所以你可以用NULL?!按笮 笔悄阈枰膬?nèi)存字節(jié);“類(lèi)型”有MEM_RESERVE (保 留)、MEM_RELEASE (釋放。和MEM_COMMIT (提交)?!氨Wo(hù)屬性”在前面章節(jié)有詳細(xì) 介紹,只能用前六種屬性。如果你要保留的是長(zhǎng)久不會(huì)釋放的內(nèi)存區(qū),就保留在較高的空間區(qū)域,這樣不會(huì)產(chǎn)生碎片 用這個(gè)類(lèi)型標(biāo)志可以達(dá)到:MEM_RESERVE|MEM_TOP_DOWN。C+程序:保留1G的空間LPVOID pV=VirtualAlloc(NULL,1000*1024*1024,MEM_RESERVE|MEM_TOP_DOWN,PAGE_READ WRITE);
35、if(pV=NULL)coutvv沒(méi)有那么多虛擬空間! vvendl;MEMORYSTATUS memStatusVirtual1;GlobalMemoryStatus(&memStatusVirtual1);coutvv虛擬內(nèi)存分配:vvendl;printf(指針地址=%xn,pV);coutvv減少物理內(nèi)存=vvmemStatusVirtual.dwAvailPhys-memStatusVirtual1.dwAvailPhysvvendl;coutvv減少可用頁(yè)文件=vvmemStatusVirtual.dwAvailPageFile-memStatusVirtual1.dwAvailP
36、ageFilevvendl;coutvv減少可用進(jìn)程空間=vvmemStatusVirtual.dwAvailVirtual-memStatusVirtual1.dwAvailVirtualvvendlvvendl;結(jié)果如下:可見(jiàn),進(jìn)程空間減少了 1G;減少的物理內(nèi)存和可用頁(yè)文件用來(lái)管理頁(yè)目和頁(yè)表。但是,現(xiàn) 在訪(fǎng)問(wèn)空間的話(huà),會(huì)出錯(cuò)的:int * iV=(int*)pV;iV0=1 ;現(xiàn)在訪(fǎng)問(wèn)會(huì)出錯(cuò),出現(xiàn)訪(fǎng)問(wèn)違規(guī)提交你必須提供一個(gè)初始地址和提交的大小。提交的大小系統(tǒng)會(huì)變成頁(yè)面的倍數(shù),因?yàn)橹荒馨错?yè) 面提交。指定類(lèi)型是MEM_COMMIT。保護(hù)屬性最好跟區(qū)域的保護(hù)屬性一致,這樣可以提 高系統(tǒng)管理的效
37、率。C+程序:提交100M的空間LPVOID pP=VirtualAlloc(pV,100*1024*1024,MEM_COMMIT,PAGE_READWRITE);if(pP=NULL) int * iP=(int*)pP;iP0=3;iP100/sizeof(int)*1024*1024-l=5;/這是能訪(fǎng)問(wèn)的最后一個(gè)地址iP100/sizeof(int)*1024*1024=5 訪(fǎng)問(wèn)出錯(cuò)保留&提交你可以用類(lèi)型MEM_RESERVEIMEM_COMMIT次全部提交。但是這樣的話(huà),沒(méi)有有效地 利用內(nèi)存,和使用一般的C+動(dòng)態(tài)分配內(nèi)存函數(shù)一樣了。更改保護(hù)屬性更改已經(jīng)提交的頁(yè)面的保護(hù)屬性,有時(shí)候會(huì)
38、很有用處,假設(shè)你在訪(fǎng)問(wèn)數(shù)據(jù)后,不想別的函數(shù) 再訪(fǎng)問(wèn),或者出于防止指針亂指改變結(jié)構(gòu)的目的,你可以更改數(shù)據(jù)所處的頁(yè)面的屬性,讓別 人無(wú)法訪(fǎng)問(wèn)。VirtualProtect (PVOID 基地址, SIZE_T 大小, DWORD 新屬性, DWORD 舊屬性)“基地址”是你想改變的頁(yè)面的地址,注意,不能跨區(qū)改變。C+程序:更改一頁(yè)的頁(yè)面屬性,改為只讀,看看還能不能訪(fǎng)問(wèn)DWORD protect;iP0=8;VirtualProtect(pV,4096,PAGE_READONLY,&protect);int * iP=(int*)pV;iP1024=9;可以訪(fǎng)問(wèn),因?yàn)樵谀且豁?yè)之外iP0=9;不可以訪(fǎng)
39、問(wèn),只讀/還原保護(hù)屬性VirtualProtect(pV,4096,PAGE_READWRITE,&protect);coutvv初始值=vviPOvvendl;/可以訪(fǎng)問(wèn)清除物理存儲(chǔ)器內(nèi)容清除頁(yè)面指的是,將頁(yè)面清零,也就是說(shuō)當(dāng)作頁(yè)面沒(méi)有改變。假設(shè)數(shù)據(jù)存在物理內(nèi)存中,系 統(tǒng)沒(méi)有 RAM 頁(yè)面后,會(huì)將這個(gè)頁(yè)面暫時(shí)寫(xiě)進(jìn)虛擬內(nèi)存頁(yè)文件中,這樣來(lái)回的倒騰系統(tǒng)會(huì)很 慢;如果那一頁(yè)數(shù)據(jù)已經(jīng)不需要的話(huà),系統(tǒng)可以直接使用。當(dāng)程序需要它那一頁(yè)時(shí),系統(tǒng)會(huì) 分配另一頁(yè)給它。VirtualAlloc (PVOID 開(kāi)始地址,SIZE_T 大小,DWORD 類(lèi)型,DWORD 保護(hù)屬性)“大小”如果小于一個(gè)頁(yè)面的話(huà),函數(shù)
40、會(huì)執(zhí)行失敗,因?yàn)橄到y(tǒng)使用四舍五入的方法“;類(lèi)型” 是 MEM_RESET。有人說(shuō),為什么需要清除呢,釋放不就行了嗎?你要知道,釋放了后,程序就無(wú)法訪(fǎng)問(wèn)了。 現(xiàn)在只是因?yàn)椴恍枰Y(jié)構(gòu)的內(nèi)容了,順便提高一下系統(tǒng)的性能;之后程序仍然需要訪(fǎng)問(wèn)這個(gè) 結(jié)構(gòu)的。C+程序:清除 1M 的頁(yè)面:PVOID re=VirtualAlloc(pV,1024*1024,MEM_RESET,PAGE_READWRITE);if(re=NULL)coutvv清除失敗!vvendl;這時(shí)候,頁(yè)面可能還沒(méi)有被清零,因?yàn)槿绻到y(tǒng)沒(méi)有RAM請(qǐng)求的話(huà),頁(yè)面內(nèi)存保存不變的, 為了看看被清零的效果,程序人為的請(qǐng)求大量頁(yè)面:C+程序:Vi
41、rtualAlloc(char*)pV+100*1024*1024+4096,memStatus.dwAvailPhys+10000000,MEM_COM MIT,PAGE_READWRITE);/沒(méi)訪(fǎng)問(wèn)之前是不給物理內(nèi)存的。char* pp=(char*)pV+100*1024*1024+4096;for(int i=0;imemStatus.dwAvailPhys+10000000;i+)ppi=V;逼他使用物理內(nèi)存,而不使用頁(yè)文件GlobalMemoryStatus(&memStatus);coutvv內(nèi)存初始狀態(tài):vvendl;cout 長(zhǎng)度=vvmemStatus.dwLengthv
42、vendl;coutvv內(nèi)存繁忙程度=vvmemStatus.dwMemoryLoadvvendl;coutvv總物理內(nèi)存=vvmemStatus.dwTotalPhysvvendl;coutvv可用物理內(nèi)存=vvmemStatus.dwAvailPhysvvendl;coutvv總頁(yè)文件=vvmemStatus.dwTotalPageFilevvendl;coutvv可用頁(yè)文件=vvmemStatus.dwAvailPageFilevvendl;coutvv可用進(jìn)程空間=vvmemStatus.dwAvailVirtualvvend;coutvv清除后=vviPOvvendl;結(jié)果如下:當(dāng)內(nèi)
43、存所剩無(wú)幾時(shí),系統(tǒng)將剛清除的內(nèi)存頁(yè)面分配出去,同時(shí)不會(huì)把頁(yè)面的內(nèi)存寫(xiě)到虛擬頁(yè) 面文件中??梢钥匆?jiàn),原先是8的值現(xiàn)在是0了。虛擬內(nèi)存的關(guān)鍵之處虛擬內(nèi)存存在的優(yōu)點(diǎn)是,需要的時(shí)候才真正分配內(nèi)存。那么程序必須決定何時(shí)才提交內(nèi)存如果訪(fǎng)問(wèn)沒(méi)有提交內(nèi)存的數(shù)據(jù)結(jié)構(gòu),系統(tǒng)會(huì)產(chǎn)生訪(fǎng)問(wèn)違規(guī)的錯(cuò)誤。提交的最好方法是,當(dāng)你 程序需要訪(fǎng)問(wèn)虛擬內(nèi)存的數(shù)據(jù)結(jié)構(gòu)時(shí),假設(shè)它已經(jīng)是分配內(nèi)存的,然后異常處理可能出現(xiàn)的 錯(cuò)誤。對(duì)于訪(fǎng)問(wèn)違規(guī)的錯(cuò)誤,就提交這個(gè)地址的內(nèi)存。釋放可以釋放整個(gè)保留的空間,或者只釋放分配的一些物理內(nèi)存。釋放特定分配的物理內(nèi)存:如果不想釋放所有空間,可以只釋放某些物理內(nèi)存?!伴_(kāi)始地址”是頁(yè)面的基地址,這個(gè)地址不一定
44、是第一頁(yè)的地址,一個(gè)竅門(mén)是提供一頁(yè)中的 某個(gè)地址就行了,因?yàn)橄到y(tǒng)會(huì)做頁(yè)邊界處理,取該頁(yè)的首地址;“大小”是頁(yè)面的要釋放的 字節(jié)數(shù);“類(lèi)型”是 MEM_DECOMMIT。C+程序:/只釋放物理內(nèi)存VirtualFree(int*)pV+2000,50*1024*1024,MEM_DECOMMIT);int* a=(int*)pV;a10=2;可以使用,沒(méi)有釋放這一頁(yè)MEMORYSTATUS memStatusVirtual3;GlobalMemoryStatus(&memStatusVirtual3);cout增加物理內(nèi)存=vvmemStatusVirtual3.dwAvailPhys-memS
45、tatusVirtual2.dwAvailPhysvvendl;coutvv增加可用頁(yè)文件=vvmemStatusVirtual3.dwAvailPageFile-memStatusVirtual2.dwAvailPageFilevvendl;coutvv增加可用進(jìn)程空間=vvmemStatusVirtual3.dwAvailVirtual-memStatusVirtual2.dwAvailVirtualvvendlvvendl;結(jié)果如下:可以看見(jiàn),只釋放物理內(nèi)存,沒(méi)有釋放進(jìn)程的空間。釋放整個(gè)保留的空間:VirtualFree (LPVOID 開(kāi)始地址,SIZE_T 大小,DWORD 類(lèi)型)“
46、開(kāi)始地址”一定是該區(qū)域的基地址;“大小”必須是 0,因?yàn)橹荒茚尫耪麄€(gè)保留的空間;“類(lèi) 型”是 MEM_RELEASE。C+程序:VirtualFree(pV,0,MEM_RELEASE);a10=2;不能使用了,進(jìn)程空間也釋放了MEMORYSTATUS memStatusVirtual4;GlobalMemoryStatus(&memStatusVirtual4);coutvv虛擬內(nèi)存釋放:vvendl;coutvv 增 加 物 理 內(nèi) 存 =vvmemStatusVirtual4.dwAvailPhys-memStatusVirtual3.dwAvailPhys vvendl;coutvv增
47、加可用頁(yè)文件=vvmemStatusVirtual4.dwAvailPageFile-memStatusVirtual3.dwAvailPageFilevvendl;coutvv增加可用進(jìn)程空間=vvmemStatusVirtual4.dwAvailVirtual-memStatusVirtual3.dwAvailVirtualvvendlvvendl;結(jié)果如下:整個(gè)分配的進(jìn)程區(qū)域被釋放了,包括所占的物理內(nèi)存和頁(yè)文件。何時(shí)釋放如果數(shù)組的元素大小是小于一個(gè)頁(yè)面4K的話(huà),你需要記錄哪些空間不需要,哪些在一個(gè)頁(yè) 面上,可以用一個(gè)元素一個(gè)Bit來(lái)記錄;另外,你可以創(chuàng)建一個(gè)線(xiàn)程定時(shí)檢測(cè)無(wú)用單元。擴(kuò)展地址
48、AWEAWE是內(nèi)存管理器功能的一套應(yīng)用程序編程接口 (API),它使程序能夠?qū)⑽锢韮?nèi)存保留為 非分頁(yè)內(nèi)存,然后將非分頁(yè)內(nèi)存部分動(dòng)態(tài)映射到程序的內(nèi)存工作集。此過(guò)程使內(nèi)存密集型程 序(如大型數(shù)據(jù)庫(kù)系統(tǒng))能夠?yàn)閿?shù)據(jù)保留大量的物理內(nèi)存,而不必交換分頁(yè)文件以供使用。 相反,數(shù)據(jù)在工作集中進(jìn)行交換,并且保留的內(nèi)存超過(guò) 4 GB 范圍。對(duì)于物理內(nèi)存小于2G進(jìn)程空間時(shí),它的作用是:不必要在物理內(nèi)存和虛擬頁(yè)文件中交換。對(duì)于物理內(nèi)存大于2G進(jìn)程空間時(shí),它的作用是:應(yīng)用程序能夠訪(fǎng)問(wèn)的物理內(nèi)存大于2G, 也就相當(dāng)于進(jìn)程空間超越了 2G的范圍;同時(shí)具有上述優(yōu)點(diǎn)。3GB當(dāng)在boot.ini上加上/3GB選項(xiàng)時(shí),應(yīng)用程序的
49、進(jìn)程空間增加了 1G,也就是說(shuō),你寫(xiě)程序 時(shí),可以分配的空間又增大了 1G,而不管物理內(nèi)存是多少,反正有虛擬內(nèi)存的頁(yè)文件,大 不了慢點(diǎn)。PAE當(dāng)在boot.ini上加上/PAE選項(xiàng)時(shí),操作系統(tǒng)可以支持大于4G的物理內(nèi)存,否則,你加再 多內(nèi)存操作系統(tǒng)也是不認(rèn)的,因?yàn)楣芾磉@么大的內(nèi)存需要特殊處理。所以,你內(nèi)存小于4G 是沒(méi)有必要加這個(gè)選項(xiàng)的。注意,當(dāng)要支持大于16G的物理內(nèi)存時(shí),不能使用/3G選項(xiàng),因 為,只有1G的系統(tǒng)空間是不能管理超過(guò)16G的內(nèi)存的。AWE當(dāng)在boot.ini上加上/AWE選項(xiàng)時(shí),應(yīng)用程序可以為自己保留物理內(nèi)存,直接的使用物理內(nèi) 存而不通過(guò)頁(yè)文件,也不會(huì)被頁(yè)文件交換出去。當(dāng)內(nèi)存
50、大于3G時(shí),就顯得特別有用。因?yàn)?可以充分利用物理內(nèi)存。當(dāng)物理內(nèi)存大于4G時(shí),需要/PAE的支持。以下是一個(gè) boot.ini 的實(shí)例圖,是我機(jī)器上的: 要使用AWE,需要用戶(hù)具有Lock Pages in Memory權(quán)限,這個(gè)在控制面板中的本地計(jì)算機(jī) 政策中設(shè)置。第一,分配進(jìn)程虛擬空間:VirtualAlloc (PVOID 開(kāi)始地址, SIZE_T 大小, DWORD 類(lèi)型, DWORD 保護(hù)屬性)“ 開(kāi) 始 地 址 ” 可 以 是 NULL , 由 系 統(tǒng) 分 配 進(jìn) 程 空 間 ;“ 類(lèi) 型 ” 是 MEM_RESERVEIMEM_PHYSICAL; “保護(hù)屬性”只能是PAGE_RE
51、ADWRITE。MEM_PHYSICAL指的是區(qū)域?qū)⑹芪锢泶鎯?chǔ)器的支持。第二,你要計(jì)算出分配的頁(yè)面數(shù)目PageCount:利用本文第二節(jié)的GetSystemInfo可以計(jì)算出來(lái)。第三,分配物理內(nèi)存頁(yè)面:AllocateUserPhysicalPages (HANDLE 進(jìn)程句柄, SIZE_T 頁(yè)數(shù), ULONG_PTR 頁(yè)面指針數(shù) 組)進(jìn)程句柄可以用GetCurrentProcess()獲得;頁(yè)數(shù)是剛計(jì)算出來(lái)的頁(yè)數(shù)PageCount;頁(yè)面數(shù)組 指針 unsigned long* ArrayPageCount。系統(tǒng)會(huì)將分配結(jié)果存進(jìn)這個(gè)數(shù)組。第四,將物理內(nèi)存與虛擬空間進(jìn)行映射:MapUserPh
52、ysicalPages (PVOID 開(kāi)始地址, SIZE_T 頁(yè)數(shù), ULONG_PTR 頁(yè)面指針數(shù)組)“開(kāi)始地址”是第一步分配的空間;這樣的話(huà),虛擬地址就可以使用了。如果“頁(yè)面指針數(shù)組”是NULL,則取消映射。第五,釋放物理頁(yè)面FreeUserPhysicalPages (HANDLE 進(jìn)程句柄, SIZE_T 頁(yè)數(shù), ULONG_PTR 頁(yè)面指針數(shù)組)這個(gè)除了釋放物理頁(yè)面外,還會(huì)取消物理頁(yè)面的映射。第六,釋放進(jìn)程空間VirtualFree (PVOID 開(kāi)始地址, 0, MEM_RELEASE)C+程序:首先,在登錄用戶(hù)有了 Lock Pages in Memory權(quán)限以后,還需要調(diào)用W
53、indows API激活這個(gè) 權(quán)限。BOOL VirtualMem:LoggedSetLockPagesPrivilege ( HANDLE hProcess,BOOL bEnable)struct DWORD Count;/數(shù)組的個(gè)數(shù)LUID_AND_ATTRIBUTES Privilege 1; Info;HANDLE Token;/打開(kāi)本進(jìn)程的權(quán)限句柄BOOL Result = OpenProcessToken ( hProcess,TOKEN_ADJUST_PRIVILEGES,& Token);If (Result!= TRUE )printf( Cannot open proces
54、s token.n ); return FALSE;/我們只改變一個(gè)屬性Info.Count = 1;/準(zhǔn)備激活if( bEnable )Info.Privilege0.Attributes = SE_PRIVILEGE_ENABLED;elseInfo.Privilege0.Attributes = 0;/根據(jù)權(quán)限名字找到 LGUIDResult = LookupPrivilegeValue ( NULL,SE_LOCK_MEMORY_NAME, &(Info.Privilege0.Luid);if( Result != TRUE )printf( Cannot get privilege
55、for %s.n, SE_LOCK_MEMORY_NAME );return FALSE;/ 激活 Lock Pages in Memory 權(quán)限Result = AdjustTokenPrivileges ( Token, FALSE,(PTOKEN_PRIVILEGES) &Info,0, NULL, NULL);if( Result != TRUE )printf (Cannot adjust token privileges (%u)n, GetLastError() ); return FALSE;elseif( GetLastError() != ERROR_SUCCESS )pr
56、intf (Cannot enable the SE_LOCK_MEMORY_NAME privilege; );printf (please check the local policy.n); return FALSE;CloseHandle( Token ); return TRUE;分配100M虛擬空間:PVOID pVirtual=VirtualAlloc(NULL,100*1024*1024,MEM_RESERVE|MEM_PHYSICAL,PAGE_READWRITE);if(pVirtual=NULL)coutvv沒(méi)有那么大連續(xù)進(jìn)程空間!vvendl;MEMORYSTATUS
57、memStatusVirtual5;GlobalMemoryStatus(&memStatusVirtual5);coutvv虛擬內(nèi)存分配:vvendl;cout減少物理內(nèi)=vvmemStatusVirtual4.dwAvailPhys-memStatusVirtual5.dwAvailPhysvvendlcoutvv減少可用頁(yè)文=vvmemStatusVirtual4.dwAvailPageFile-memStatusVirtual5.dwAvailPageFilevvendl;coutvv減少可用進(jìn)程空間=vvmemStatusVirtual4.dwAvailVirtual-memStat
58、usVirtual5.dwAvailVirtualvvendlvvendl;結(jié)果如下:可以看見(jiàn),只分配了進(jìn)程空間,沒(méi)有分配物理內(nèi)存。分配物理內(nèi)存:ULONG_PTR pages=(ULONG_PTR)100*1024*1024/sysInfo.dwPageSize;ULONG_PTR *frameArray=new ULONG_PTRpages;如果沒(méi)激活權(quán)限,是不能調(diào)用這個(gè)方法的,可以調(diào)用,但是返回FALSEBOOL flag=AllocateUserPhysicalPages(GetCurrentProcess(),&pages,frameArray);if(flag=FALSE)cout
59、vv分配物理內(nèi)存失敗!vvendl;MEMORYSTATUS memStatusVirtual6;GlobalMemoryStatus(&memStatusVirtual6);coutvv物理內(nèi)存分配:vvendl;cout 減 少 物 理 內(nèi) 存=memStatusVirtual5.dwAvailPhys-memStatusVirtual6.dwAvailPhysendl cout 減 少 可 用 頁(yè) 文 件 =memStatusVirtual5.dwAvailPageFile-memStatusVirtual6.dwAvailPageFileendl;cout 減 少 可 用 進(jìn) 程 空
60、間 =memStatusVirtual5.dwAvailVirtual-memStatusVirtual6.dwAvailVirtualendlendl;結(jié)果如下:分配了物理內(nèi)存,可能分配時(shí)需要進(jìn)程空間管理。物理內(nèi)存映射進(jìn)程空間:int* pVInt=(int*)pVirtual;pVInt0=10;這時(shí)候訪(fǎng)問(wèn)會(huì)出錯(cuò) flag=MapUserPhysicalPages(pVirtual,1,frameArray);if(flag=FALSE)coutvv映射物理內(nèi)存失敗!vvendl;MEMORYSTATUS memStatusVirtual7;GlobalMemoryStatus(&memS
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度學(xué)生傷害賠償協(xié)議書(shū)(校園意外)
- 二零二五年度道路運(yùn)輸企業(yè)司機(jī)薪酬管理合同
- 2025年度物業(yè)保潔項(xiàng)目管理勞動(dòng)合同
- 二零二五年度業(yè)主委員會(huì)與物業(yè)服務(wù)社區(qū)停車(chē)管理合同
- 2025年度門(mén)面房出租與租賃合同爭(zhēng)議解決協(xié)議
- 典當(dāng)與拍賣(mài)服務(wù)作業(yè)指導(dǎo)書(shū)
- 2025年IT服務(wù)管理培訓(xùn)課件
- 二手住房出售協(xié)議
- 網(wǎng)絡(luò)直播行業(yè)主播言論免責(zé)協(xié)議
- 客戶(hù)關(guān)系管理軟件開(kāi)發(fā)外包合同書(shū)
- 2025年高三第二學(xué)期物理備課組教學(xué)工作計(jì)劃
- 丁香園:2024年12月全球新藥月度報(bào)告-數(shù)據(jù)篇
- 生產(chǎn)與運(yùn)作管理-第5版 課件全套 陳志祥 第1-14章 生產(chǎn)系統(tǒng)與生產(chǎn)運(yùn)作管理概述 -豐田生產(chǎn)方式與精益生產(chǎn)
- 2025年湖南理工職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測(cè)試近5年常考版參考題庫(kù)含答案解析
- 2024年西安航空職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測(cè)試歷年參考題庫(kù)含答案解析
- 2024年港作拖輪項(xiàng)目可行性研究報(bào)告
- 課題申報(bào)書(shū):“四新”建設(shè)與創(chuàng)新創(chuàng)業(yè)人才培養(yǎng)基本范式研究
- 春季高考高職單招數(shù)學(xué)模擬試題七套含答案
- 2024-2025學(xué)年陜西省寶雞市高三上學(xué)期高考模擬檢測(cè)(一)英語(yǔ)試題(含解析)
- 2025年企業(yè)的演講稿例文(2篇)
- 電瓶三輪車(chē)安全培訓(xùn)
評(píng)論
0/150
提交評(píng)論