1. 程式人生 > >32位作業系統記憶體大小識別

32位作業系統記憶體大小識別

500元、300元、150元......隨著DDR2價格的逐漸崩盤,目前連2GB DDR2-800記憶體的價格也已經跌至百元,越來越多的朋友為愛機裝上了4GB記憶體。隨著4GB電腦的逐漸增加,一個長期存在的問題又再次被人們所關注:為何我只能看到3.25GB實體記憶體?

1.jpg (58.97 KB)

2009-4-20 18:02


  無論是WinXP-32bit還是Vista-32bit,所有的使用者都可以發現自己的工作管理員中最多隻顯示3.25GB實體記憶體,更甚者還會有2.8GB甚至更低的數值出現。我們花錢購買的記憶體就這樣白白不見了麼?   人們當然不會允許這樣的事情發生,於是各種論壇上展開了關於4GB記憶體的大量討論。重灌系統、開啟PAE、使用Ramdisk、開啟Memory Remapping等等各種手段層出不窮,所有人都想找回那失去的記憶體。再逐一嘗試之後,人們發現始終能夠在32bit系統上找到那0.75GB記憶體的下落。人們所寄希望的Vista系統也僅僅是能夠在系統屬性上看到4.00GB的字樣,裝置管理器的實體記憶體依然安逸的保持在3.25GB。期間,各大電腦網站和雜誌也刊登了一些關於這方面的文章,介紹了大量內容,最終人們將一切歸罪於32bit作業系統。   這樣的審判似乎很正確,畢竟我們可以真實的看到64bit系統下那>3.25GB的實體記憶體顯示,32bit系統顯然貪汙掉了0.75GB記憶體。然而事實上,作業系統卻在這裡成為了不折不扣的替罪羊。因為事實上即使是在64bit系統中,記憶體同樣會被“侵蝕”;而32bit系統也同樣可以使用超過4GB的記憶體。為了讓廣大網友都能夠了解事實究竟,今天筆者就為作業系統客串一次辯護律師,為其平反這個記憶體貪墨案,找尋那失落的記憶體。真相永遠只有一個!

  注:文字將以Intel當代晶片組的記憶體分配機制為例講述,其他品牌晶片組在細節上或許有與本文所描述不同之處,但結論上不會有太大出入。

32bit作業系統,32bit處理器,有著32bit定址能力,可以訪問2^32 = 4G實體地址,於是擁有識別4GB記憶體的能力,這似乎是完全順理成章的事情。然而其中有一個關鍵,什麼是實體地址?實體地址就是實體記憶體的地址?非也。實體地址是指處理器和系統記憶體之間所用到地址,我們可以簡單理解成是CPU“極方便訪問的地址”。這個地址並非實體記憶體獨享,儘管通常它基本都會與實體地址重疊,但也可以根據需要被其他裝置佔用,使得實體記憶體實際上只能夠佔用這4GB地址中的一部分。

2009-4-20 18:03


  認真看看上面這個P45晶片組的系統地址區域圖。圖中的方塊代表的是不同區域的“地址”,這些地址囊括了一臺電腦中所有能和作業系統以及晶片組關聯的裝置地址,而不僅僅是“實體記憶體地址”。同樣的,那個4G的紅線代表的是第4G個Byte的地址,並不是4GB實體記憶體的分界線,儘管記憶體控制器很多時候確實會讓它們重疊在一起。P45晶片組是一款支援36bit定址的產品,即可以支援64GB地址,但為了去迎合作業系統以及各種軟體,因此需要保證系統運轉所必須的所有裝置地址都可以在4GB範圍內找到,否則會給硬體32bit驅動程式的製作帶來很多麻煩,對驅動程式相容性造成極大程度的影響。很顯然,讓一個系統正常執行並不僅僅包括記憶體,還要包括各種I/O裝置等。在4GB的定址範圍內,實體記憶體實際上只佔據了一塊,就是那個被稱為Main Memory Address Range的區域(圖中綠色框)。安裝4GB以下記憶體的話,Windows的工作管理員會確認1MB至TOLUD暫存器數值作為系統可用的實體記憶體(無板載顯示卡佔用)。TOLUD全稱是Top of Low Usable Dram,這個16bit暫存器由BIOS賦予一個適當的數值,其含義是4GB地址內的可用實體記憶體地址頂端。如果安裝2GB記憶體,那麼TOLUD的數值就是7FFFFFFFh,也就是16進位制的2GB(加上0地址),工作管理員一般會顯示2046MB(見小貼士)。既然記憶體並不能佔據整個4GB地址,那麼其他地址主要被誰佔據了呢?

  小貼士:相信不少非4GB使用者會發現自己的記憶體同樣被偷吃了幾MB,比如2GB記憶體使用者通常在裝置管理器中只能看到2047MB或者2046MB記憶體等等。這是因為還有兩塊地址範圍被佔據,這兩個區域分別是LegacyAddress Range和TSEG,他們會使用一部分記憶體(比如載入系統BIOS)。由於這兩個區域都處於TOLUD以下的地址範圍內,包含了BIOS

等底層部件的Legacy Address Range更是固定佔據00000000h000FFFFFh1MB最底層地址空間,所以無論系統安裝了多少記憶體,Windows工作管理員顯示的數值都會受到影響。

2009-4-20 18:03


  上面的圖中展示了00000000h至FFFFFFFFh共4GB地址的詳細分配(上圖中方塊大小於佔用地址多少無關),4GB實體記憶體本身會自然排布其上,但會有一些優先順序更高的分派來爭奪實體地址空間,使得真正留下的實體記憶體只在Main Memory區域,而其他部分通常會佔據幾MB最多十幾MB的地址空間,但其中有一個地址大戶:PCI Memory Address Range(PCI Memory Range)。

PCI Memory Address Range這一部分包含了各種I/O裝置,系統匯流排等部分所需的地址,上面的圖中我們可以看到ICH10的磁碟控制器、PCIE(顯示卡)等該系統現有裝置所佔據的地址範圍。這些I/O裝置地址被通過一種叫做MMIO的技術使得CPU可以高速便捷的訪問它們。根據裝置狀況的不同,PCIMemory Address Range的大小也會發生變化,這都一切取決於硬體本身及硬體驅動的需求,例如晶片組、顯示卡等等。

2009-4-20 18:05


  小貼士:MMIO全稱是Memory-mapped I/O,是一種在CPU和外圍裝置之間執行輸入輸出功能的途徑。MMIO簡單說就是將各種外圍裝置的控制暫存器對映到實體記憶體地址上,CPU可以像訪問記憶體一樣方便的訪問I/O裝置,而無需重複再三的去呼叫IO控制函式。CPU會將自己的定址空間預留一塊用於I/O裝置,這也意味著記憶體地址被佔用了一塊,但並不會真的佔用實體記憶體儲存空間。

2009-4-20 18:05


  沒有板載顯示卡的話,PCIMemory Address Range基本可以與MMIO區域劃等號。MMIO會佔據TOLUD至4GB的地址空間,不過這只是將實體地址分派給各種外圍裝置,而不會真的佔用實體記憶體。上圖中的系統只有2GB記憶體,那麼TOLUD的值就是2GB(7FFFFFFFh),PCI Memory Address Range也就自動佔據了80000000h至FFFFFFFFh這剩下2GB的地址空間。而且很明顯,它不佔用記憶體,因為後面2GB根本沒有記憶體。MMIO區域所佔據的地址實際上對應的物理裝置是外圍裝置的暫存器之類,相對於這些裝置的暫存器來說,MMIO是一塊邏輯地址區間。

2009-4-20 18:06


       上圖展示了P45晶片組(Intel晶片組)的典型MMIO分配,裡面包含了大量系統所必須的內容:High BIOS、DMI匯流排、FSB中斷、APIC、PCIE等多方面的裝置地址。這些都是一款Intel晶片組正常執行所必須的東東,尤其是DMI匯流排(連線Intel晶片組南北橋)管理著主機板上的大多數IO裝置,它們自然必須在任何時候都享受著MMIO所分配的地址,而這個地址範圍通常就是0.75GB。

2009-4-20 18:06


  DFI的X58主機板給出了一個很有意思的選項,名叫MemoryLowGap。這個選項可以讓使用者自定義選擇TOLUD的地址,或者說自定義選擇MMIO區域的大小。該選項的範圍為1024M至3072M,即MMIO區域的大小為1024MB-3072MB。可能是因為需要對映到實體地址的暫存器數量很大,一些頂級顯示卡的驅動程式會要求比較大的MMIO區域支援,例如NVIDIA的GTX280、GTX295之類。4GB記憶體使用者甚至可以發現,當更換顯示卡後,裝置管理器顯示的實體記憶體大小竟然也會發生變化,甚至會降低到3GB以下的數值,這就是因為某些高階顯示卡申請了更大的MMIO,使得記憶體在4GB以下的地址空間被進一步壓縮,我們可以在Windows的裝置管理器內看到地址分佈的變化。

2009-4-20 18:06



  當我們把DFIX58主機板BIOS中的Memory LowGap調至一個鉅額的數值之後,上圖中的景象就出現了。由於MMIO的進一步擴張,我們發現連2GB的記憶體竟然也被侵蝕了好大一塊,50000000h(1280MB)之後的地址就已經開始被MMIO佔據。4GB地址就像是一輛擁擠的公共汽車,空間總共就那麼大,PCIMemory Address Range擠上去了、滿載了,記憶體自然就上不去了。難道記憶體就這麼白費了?先不用著急,繼續向下看,我們會把記憶體找回來的。

讓我們再來溫習一下這張圖,並再次明確一件事情:PCI Memory Address Range中的MMIO佔去的僅僅是實體地址,並不會去佔據記憶體空間。每個記憶體顆粒中每個可以儲存1bit的電晶體本身並不會擁有地址,所有的地址都是由系統進行分配的。這一切的地址排布與作業系統是多少位並無太多關聯,而作業系統方面對MMIO大小的影響主要來自於系統自身驅動以及裝置驅動程式等方面的要求。因此我們可以發現在一些預設功能開啟較少,硬體驅動地址開銷較少的系統中(如Win Sever),工作管理員顯示的實體記憶體會大一些(例如3.6GB)。因為此時的MMIO相對較小。從根本上來說,這是晶片組來自於相容性方面的考量,必須讓MMIO位於4GB以內。

2009-4-20 18:08


  由於相容性的考量,即使使用了64bit作業系統和64bit處理器,MMIO仍然會被晶片組安置於4GB地址以內。MMIO必須佔用這段地址空間,且MMIO有著比記憶體更高的優先順序,實體記憶體又會老老實實的自然排布,這使得當安裝了接近4GB或更多實體記憶體時,PCI Memory Address Range必然會與實體記憶體交疊,在整個實體記憶體地址中形成一個MemoryHole。

2009-4-20 18:08


  小貼士:MemoryHole其實很好理解,就像上面的圖中那樣,Main Memory被分成了兩段,而那段被佔用的地址空間就像一個“洞”(Hole),所以稱之為Hole。。。。。。上面圖中PCI Memory Address Range就充當了這個Hole的角色,它並不佔用記憶體儲存空間,只是一個實體地址上的橫亙,使得Hole的地址與記憶體地址發生了重疊。

2009-4-20 18:08



  晶片組設計師們自然有其他的考量去解決實體記憶體地址的分配問題,畢竟會白白浪費記憶體的晶片組是不討人喜歡的。既然4GB以下地址如此緊張,我們為何不將實體記憶體分配到更高的地址空間去呢?於是,TOM、 TOUUD暫存器以及RECLAIMBASE、RECLAIMLIMIT暫存器誕生了。

TOM即“Top of Memory”,其描述的是系統上所安裝的實體記憶體的總量。TOM暫存器值並不見得代表最高記憶體地址,因為MMIO的地址分配要優先於TOM暫存器,記憶體地址中基本都會存在一些hole(PCI Memory Address Range),所以TOM暫存器的地址最終還需要加上這些hole的地址,從而會更高一些。TOM暫存器之下將會有1-64MB記憶體被Manageability Engine佔用(圖中的EP-UMA),這是確確實實被佔有的記憶體。

2009-4-20 18:09


  TOUUD即“Top of Upper UsableDRAM”,其描述的是可設定地址的實體記憶體總量。TOLUD暫存器會始終在4GB記憶體地址以下工作,但我們知道現在的主流晶片組都能安裝高達16GB的記憶體,TOUUD就可以解決這個問題。TOUUD會在4GB以上地址定義實體記憶體範圍,這個範圍會從4GB到可用實體記憶體頂端(TOM),經過鑑定的實體記憶體可以直接被使用。這並不受作業系統的影響,而是晶片組的工作,也就是至少BIOS肯定是能夠接受16GB記憶體的。

  OK,現在我們要回收那塊被“佔用”的記憶體地址了。MMIO佔據了TOLUD到4GB的地址空間,所以晶片組需要去回收這段地址重疊的實體記憶體。實體記憶體並不能直接搬家,晶片組會開啟一個remap window(Main Memory Reclaim Address Range),其底端地址由RECLAIMBASE暫存器定義,頂端地址由RECLAIMLIMIT暫存器定義,總大小會與被MMIO佔用的記憶體地址範圍完全相等。然後會將原本將落在TOLUD至4GB地址之間的實體記憶體回收,重對映到4GB以上EP Stolen Base之下的地址空間中,屬於remap window中的地址都會去對應由TOLUD至4GB的這段實體記憶體。

  注:由於筆者目前不確定晶片組的Memory Reclaim功能是否可以通過主機板BIOS開關,所以某些品牌主機板BIOS中的Memory (Hole) Remapping選項可能控制了Memory Reclaim功能的開關。

2009-4-20 18:09



  OK,現在我們要回收那塊被“佔用”的記憶體地址了。MMIO佔據了TOLUD到4GB的地址空間,所以晶片組需要去回收這段地址重疊的實體記憶體。實體記憶體並不能直接搬家,晶片組會開啟一個remap window(Main Memory Reclaim Address Range),其底端地址由RECLAIMBASE暫存器定義,頂端地址由RECLAIMLIMIT暫存器定義,總大小會與被MMIO佔用的記憶體地址範圍完全相等。然後會將原本將落在TOLUD至4GB地址之間的實體記憶體回收,重對映到4GB以上EP Stolen Base之下的地址空間中,屬於remap window中的地址都會去對應由TOLUD至4GB的這段實體記憶體。

  在主機板BIOS中的Memory Remapping(也有的叫Memory Hole Remapping)實際上控制的就是晶片組(記憶體控制器)的MemoryReclaim,只有當開啟這個選項的時候晶片組才會回收與MMIO交疊的記憶體。某些主機板,尤其是採用award bios的主機板上可能沒有這個選項(例如技嘉主機板),但事實上該選項其實都預設開啟了,因為此功能任何時候都完全沒有關閉的需要。

  儘管晶片組的MemoryReclaim功能為我們回收了記憶體,但我們的工作管理員現在還不能顯示它們,因為我們的實體地址只有4GB,MMIO會佔據一部分地址。被置於4GB以上地址區間的記憶體顯然早已超出了32bit定址範圍。不過我們有辦法去利用那些位於4GB地址以上的記憶體。想知道究竟?請繼續向後看。

在早年的計算機中,地址的轉換很單純,有效地址就直接等於物理儲存器的地址,這適合同一時間只有一個程序在運作。但Windows不會只有一個Window,多程序並存是現代計算機的基本情形。後來人們決定為每個程序劃定一塊專用記憶體區域,這樣可以讓多個程序同時運作。但這種分段方式會讓記憶體在程序開開關關的過程中產生很多碎片,很多小塊記憶體無法被利用。由於記憶體空間總是相對有限的,因此應用程式也不能瘋狂的將所有東西直接塞進記憶體當中。同時我們也不能依賴硬碟這個緩慢的二級儲存器去充當記憶體,那實在太慢了。為了調和這個矛盾,作業系統都引入了虛擬記憶體機制。

2009-4-20 18:10


  Windows的虛擬記憶體並非簡單的指位於我們硬碟上的那個pagefile.sys檔案,或者是在記憶體裝不下的時候用於應急的“模擬記憶體”。在當代Windows系統中,任何一個程序都會被賦予其自己的虛擬地址空間,這是一種邏輯地址空間,並不存在實體,該虛擬地址空間可以覆蓋了一個相當大的範圍。對於一個32位程序,其可以擁有的虛擬地址空間為2^32=4GB,典型情況為2GB使用者空間,2GB系統核心空間(最大可調整為3GB使用者空間和1GB核心空間),這與安裝了多少實體記憶體沒有任何關係。每個程序的虛擬地址空間都會被標上各自的ID,這樣兩個程序之間的虛擬地址就不會互相干擾。雖然每一個32位程序可使用4GB的地址空間,但並不意味著每一個程序實際擁有4GB的實體地址空間或使用4GB實體記憶體,虛擬地址僅僅是一種邏輯地址。

2009-4-20 18:10



  應用程式自然不能總在看不見摸不著的虛擬地址裡溜達,最終還是需要實實在在的物理儲存器關聯。應用程式會去為其虛擬地址申請物理儲存空間,這個空間通常會小於應用程式的總虛擬空間。這裡所說的物理儲存器並不侷限於計算機記憶體,還包括在磁碟空間上建立的頁檔案(pagefile.sys),其儲存空間大小為計算機記憶體和頁檔案儲存容量之和(所以Windows自動管理時的pagefile.sys是很大的)。由於通常情況下磁碟儲存空間要遠大於記憶體的儲存空間,因此頁檔案的使用對於應用程式而言確實相當於透明的增加了其所能使用的記憶體容量,只是速度慢了點。有了虛擬記憶體的存在,程式本身就不用完全裝入記憶體,或者完全存於硬碟,系統會將目前需要的部分讀入記憶體處理,暫時不需要的就放在硬碟的頁檔案留作交換。不過CPU並不能直接去訪問磁碟上的資訊,每次磁碟訪問都必須通過記憶體,所以若所需的內容在磁碟上的頁檔案中,就需要先載入到記憶體然後訪問。

  應用程式本身並不關心自己佔用的記憶體大小,它只要求提交物理儲存器,無論是磁碟還是記憶體。那麼自然是儘量分配更多的高速的記憶體作為物理儲存器最佳,所以我們也知道記憶體大的機器在大量應用程式啟動時會快。當一個程序的虛擬記憶體提交的物理儲存器是實體記憶體時,我們就可以省去從磁碟的頁檔案載入資料到實體記憶體的時間,程式的工作效率自然就會提高。儘管我們的記憶體超出了32bit系統的地址結構範圍,但我們只要將4GB地址以上的實體記憶體為虛擬記憶體所用就不會浪費記憶體了。

實體地址擴充套件(PAE)是早在Pentium Pro時代就有的東東,它可以提高IA32處理器應對4GB以上記憶體的能力。當啟用 PAE之後,Windows作業系統將從兩級線性地址轉換變為三層地址轉換,額外的一層轉換用於訪問超過4GB地址的實體記憶體,可以將超出4GB地址的實體記憶體對映為應用程式程序的虛擬地址空間以提升虛擬記憶體效能。地址視窗擴充套件(AWE)更是可以將未分頁的實體記憶體轉換到程序的虛擬地址。通過PAE,我們可以完整的利用到被回收至4GB以上地址的那部分記憶體。

2009-4-20 18:12


  至於開啟PAE的方法網上遍地都是,我想就不用在這裡多費筆墨了。而且事實上,作業系統多數情況下會自動開啟PAE,在使用多核心處理器時,無論安裝多少實體記憶體,Windows都會因處理器需要而預設開啟PAE功能。換句話說,在這個雙核心處理器普及的時代我們基本上不用去考慮PAE的開啟問題。

2009-4-20 18:12


  現在萬事俱備,只要晶片組與PAE都正常運作,那麼我們的4GB記憶體就1位元組都不會少。

  通過前面的講述,我們現在明白了三點:1、MMIO只佔據地址不佔據記憶體空間;2、現代的晶片組和記憶體控制器完全具備回收(轉移)與MMIO交疊的記憶體的能力;3、32bit作業系統通過PAE可以擁有訪問位於4GB地址以上的記憶體的能力。

2009-4-20 18:15


  然而多數人都會發現,我們雖然已經找到了開啟4GB大門的鑰匙,但卻始終找不到鑰匙孔。作業系統在多核心狀況下PAE強制開啟,處理器早在N年前就支援了PAE 36bit定址,而PAE也處於活動狀態,但我們始終就發現不了那完整的4GB記憶體。所有人都卡在了這裡。

2009-4-20 18:15





  事實上,Windows內部的一些設定(不排除是bug)限制了我們的記憶體使用,桌面版Windows(包括Vista旗艦版)的36bit定址功能無論PAE是否處於啟用狀態都無法訪問32bit以上地址,甚至可以說PAE根本是無效的。這樣就無法去訪問被晶片組轉移到高地址位的記憶體,哪怕該系統本身完全具備了這樣的能力。而同樣最大隻支援4GB實體記憶體的Windows Sever 2008標準版卻可以通過PAE訪問高位地址,去享受被晶片組回收和轉移那部分記憶體。筆者現在並不知道究竟是那些內部設定或bug限制了桌面系統的PAE功能,但我們有辦法去改變現狀。

2009-4-20 18:15





  首先我們需要準備WindowsSever 2008標準版的tokens.dat檔案和序列號。在C:WindowsServiceProfilesNetworkServiceAppDataRoamingMicrosoftSoftwareLicensing中我們可以看到一個名為tokens.dat的檔案,這一個軟體許可檔案,我們需要在他身上做點文章。該檔案正常狀態始終為Software Licensing服務呼叫,是不可修改或替換的,我們可以安全模式或者在禁用Software Licensing服務之後進行替換。我們要做的事情,就是用WindowsSever 2008標準版的許可檔案替換Vista的許可檔案。   當檔案替換完成之後,登出或者重啟之後系統會提示當前序列號(Vista的序列號)不可用,要求輸入新序列號,同時強制不可進入系統(安全模式正常)。此時我們輸入Windows Sever 2008標準版的序列號,無論啟用是否成功,序列號都會正確替換,同時重啟後我們可以正常進入系統(若未啟用會提示3天內啟用)。許可檔案對Vista的一些設定進行了調整,比如關閉Aero功能,開啟事件跟蹤程式之類Windows Sever 2008的特性。當然作業系統本身依然是Vista,我們可以開啟Aero以及關閉不需要的伺服器功能。

2009-4-20 18:15


  歡呼吧,各位!儘管作業系統仍然是Vista,但由於內部某些設定的自動調整使得我們的作業系統完完整整、千真萬確的利用到了所有的4GB記憶體。我們的記憶體不僅誰也沒動,而且安然無恙的全部回來了。(若出現只顯示2GB記憶體的狀況,再次重啟即可)

2009-4-20 18:15


  看看裝置管理器中的地址分配,MMIO還是牢牢霸佔著4GB以下的實體地址,但晶片組的MemoryReclaim功能幫我們找回了記憶體。而作業系統嘛,再啟用一次就一切正常了。

通過晶片組的 Memory Reclaim機制和CPU、作業系統PAE功能的正常運作,我們在32bit桌面系統上完整的利用到了4GB記憶體。這一切不能怪32bit作業系統本身,恐怕只能怪微軟的設定(或bug)。不過無論如何,我們的記憶體誰也沒動,並沒有被任何東東佔據我們的電晶體。  如果希望變回原版的Vista系統,只需要按照相同地方法替換Vista版的tokens.dat檔案,並進行序列號更換即可。事實上我們或許不需要這樣麻煩的去替換系統許可檔案,相信只是一些內部設定妨礙了桌面系統PAE的正常發揮。筆者暫時恐怕無法找出究竟是哪一項設定造成的影響,期待各位熱心的網友去發掘。

  修改許可檔案之後會有一個後遺症,那就是Windows Update會認為你的作業系統是WindowsSever 2008,因而提供Windows Sever 2008版補丁下載。但是由於我們的作業系統是貨真價實的Vista,所以安裝Windows Sever 2008補丁會造成一些問題,請各位通過其他途徑安裝正確的Vista版補丁。

  後記:這篇文章寫得還真是一波三折,由於意外的提早放出弄得我著實有點搓手不及。儘管我肯定了我的判斷和分析是正確的,但始終找不到一個最正確的、最直觀的最終答案。不過也正是意外的提早放出,藉助網友的群策群力最終得到了一個圓滿的結果。