1. 程式人生 > >32位程式超過2G記憶體空間定址問題

32位程式超過2G記憶體空間定址問題

32位程式超過2G記憶體空間定址問題

由於在32位處理器架構下,對記憶體的訪問限制在4GB以下的空間。為了突破 4GB的限制,現在的32位至強處理器採用一種叫PAE(實體地址擴充套件)的技術,來實現對超出4GB空間的實體地址的訪問。PAE實際上採用了36位的地址匯流排,這樣理論上可以支援64GB記憶體空間的定址。

  PAE使得處理器可以支援訪問更多的記憶體空間,但是這還需要作業系統的支援。由於作業系統本身也是32位的,所以需要在作業系統上做相應的處理來支援處理器。Windows系統採用AWEAddress Windowing Extension)來進行處理。具體結構如圖2所示。此外,

Linux系統在2.4核心以後也支援PAE和超過4GB的記憶體空間處理。

   

32位系統,地址空間是4G。這個沒錯。使用者空間指的是應用程式可以直接訪問的地址,系統空間指的是應用程式不能直接訪問,必須轉到核心模式,由作業系統訪問。任何作業系統都分使用者空間和系統空間,Unix, Linux都是。

       Windows95, Windows 98, WindowsME系列2G使用者空間 + 2G系統空間, 2G的系統空間中含有多個程序共享記憶體的空間和Win16的程式的程式碼,這就是Win9x系列容易宕機的原因之一。

WinNT, Win2000, WinXP系列2G使用者空間 + 2G

系統空間.(沒有Win9x系列的程序共享記憶體等等)

那麼是不是我啟動10個應用,那作業系統佔有了10*2G這麼多空間?

       首先,要搞清楚記憶體和地址空間的區別。記憶體是記憶體,地址空間是地址空間(太累了,我用memory代替記憶體,address space代替地址空間吧)不管你有多少memory,256,還是512M,

32位系統的每個應用都有4G的地址空間(只不過它不能訪問上2G罷了).win2000,你的程式最多可以使用2G空間,並不是說你還就可以分配2G的記憶體了,一般情況下,記憶體分配到

一個值是會失敗的。比如,你的物理memory = 256M,你的頁交換檔案大小=256M

,那麼你分配個516M記憶體看看,失敗!實體記憶體和頁交換檔案加起來才512M.

       其次,作業系統真的佔有了2G的記憶體嗎?也不是。你的程式啟動後,作業系統的程式碼和資料對映到程式的上面2G的空間,只是對映,不是說再啟動一個例項放那兒。作業系統要對映一片記憶體的內容到一個區域是多簡單的事情。作業系統一般把系統程式碼和資料對映到應用程式的上面2G的同一個地方。2個應用程式,它的上面2G空間的程式碼資料大致上一樣(不完全一樣,因為還是有些和應用程式相關資訊,不過應用程式訪問不到,得由系統通過核心態訪問).嚴格說來,下面2G也不是應用程式都能用,064K這個空間就不能用,至於為什麼,回到DOS時代吧!如果沒搞多DOS那就不必要深究了。總之這是故意的。你的指標指到這兒肯定會出錯,讀都不能讀。故意不讓你讀!

哈哈。

       其實大多數應用程式比如你用VC寫個程式,它的入口地址是從4M開始,也就是0x00400000,你看看 yourApp.hInstance的值吧!它就等於0x00400000.越講越遠了,

為什麼hInstance是程式的入口地址,跑題了!別扔磚頭啊!

那麼應用程式怎麼申請大於2GB的空間呢?

辦法1:就是上面的朋友提過的 通過 /3GB或者/USERVA開關。

boot.ini 裡頭加上這個開關,系統會讓出1G給應用程式訪問。系統自己只用1G。這樣子不是什麼好辦法。微軟臨時的方案而已。應用程式link時加上 LARGEADDRESSAWARE,在生成EXE的時候設定一個標誌位,這個位系統看到了就讓你訪問 3G的空間(但是記憶體+頁交換太小,你分配一樣會失敗).

/3GB指定3G/USERVA指定一個值,不是死的3G.

辦法2:通過AWE (Address Window Extension),地址窗擴充套件

窗?是的,窗。你可以人認為是一個buffer,用來作為中間物,給2邊的東西倒騰。

socket接受傳送資料也有窗的概念,一樣的。

       要細看AWE,你到MSDN上查關鍵是AWE或者Address Window ExtensionGoogleGoole一把。你有了2G甚至更多的記憶體(啥機器都有,你不能懷疑一個32位系統裝個20G記憶體會有問題吧?硬體可以做的)可以這麼幹。沒有的話就別這麼做了,沒什麼用.AWE的原理很簡單,你在比如4G的實體記憶體上,分配的一片實體記憶體X, 你再分配的一片虛擬記憶體(地址空間)Y,把 和 通過address window對映。你可以在這片虛擬記憶體裡頭訪問4G的實體記憶體。最多訪問多少要看你的引數設定了。

       AllocateUserPhysicalPages分配實體記憶體, VirtualAlloc申請虛擬記憶體,MapUserPhysicalPages進行對映。沒什麼難的.MSDN有個sample做這個事情,看看吧這麼多關鍵字了應該好查到了。程式碼我不貼了 ,佔篇幅。

       順便說一下,記憶體檔案對映並不把什麼對映到(2~4G)這範圍。它是程序共享資料的方式,並不是擴大記憶體的方式。不過如果你有個大硬碟,建立這麼個對映來儲存/修改資料也是可以的,這不要求大的記憶體。和記憶體沒關係。