C#編程-48:文本控件復習筆記_彭世瑜_新浪博客
1301
2022-05-29
一、實模式下內(nèi)存分配機制
在8086或者80186以前,要運行一個程序,操作系統(tǒng)會把這些程序全都裝入內(nèi)存,程序都是直接運行在物理內(nèi)存上的,也就是說程序中訪問的內(nèi)存地址都是實際的物理內(nèi)存地址。當計算機同時運行多個程序時,必須保證這些程序用到的內(nèi)存總量要小于計算機實際物理內(nèi)存的大小。
例如某臺計算機總的內(nèi)存大小是128M?,現(xiàn)在同時運行兩個程序 A和B ,A需占用內(nèi)存10M?, B需占用內(nèi)存110M?。計算機在給程序分配內(nèi)存時會采取這樣的方法:先將內(nèi)存中的前10M分配給程序 A ,接著再從內(nèi)存中剩余的118M中劃分出?110M分配給程序B 。這種分配方法雖然可以保證程序A和程序B都能運行,但是這種簡單的內(nèi)存分配策略會導致很多問題:
問題 1 :進程地址空間不隔離。由于程序都是直接訪問物理內(nèi)存,所以惡意程序可以隨意修改別的進程的內(nèi)存數(shù)據(jù),以達到破壞的目的。有些非惡意的,但是有 bug 的程序也可能不小心修改了其它程序的內(nèi)存數(shù)據(jù),就會導致其它程序的運行出現(xiàn)異常。這種情況對用戶來說是無法容忍的,因為用戶希望使用計算機的時候,其中一個任務失敗了,至少不能影響其它的任務。
問題 2 :內(nèi)存使用效率低。在 A 和 B 都運行的情況下,如果用戶又運行了程序 C ,而程序 C 需要 20M 大小的內(nèi)存才能運行,而此時系統(tǒng)只剩下 8M 的空間可供使用,所以此時系統(tǒng)必須在已運行的程序中選擇一個將該程序的數(shù)據(jù)暫時拷貝到硬盤上,釋放出部分空間來供程序 C 使用,然后再將程序 C 的數(shù)據(jù)全部裝入內(nèi)存中運行??梢韵胂蟮玫剑谶@個過程中,有大量的數(shù)據(jù)在裝入裝出,導致效率十分低下。
問題 3 :程序運行的地址不確定。當內(nèi)存中的剩余空間可以滿足程序 C 的要求后,操作系統(tǒng)會在剩余空間中隨機分配一段連續(xù)的 20M 大小的空間給程序 C 使用,因為是隨機分配的,所以程序運行的地址是不確定的。
二、虛擬地址空間介紹
操作系統(tǒng)讓每個進程都有自己的虛擬地址空間(Virtual Address Space,簡稱VAS)。以32位進程為例,每個進程都有0x00000000 ~ 0xFFFFFFFF(4GB)的虛擬地址空間,所以每個進程都可能分配到0x123456地址的內(nèi)存,但這個地址不能在進程間相互訪問。
因為這些都是“虛擬”的地址空間,這些“地址”都不能直接使用,CPU在尋址的時候雖然是按照虛擬地址來尋址的,但是還要通過MMU(內(nèi)存管理單元)來將虛擬地址轉(zhuǎn)換為物理存儲器(如內(nèi)存等)上的物理地址:
從圖上可以看出,進程A和B雖然都有地址0x123456,但它們分別對應的物理地址不一樣。
##三、虛擬地址空間分區(qū)
進程的虛擬地址空間雖然很大,但是它被劃分成了很多分區(qū),供Ring3層應用程序使用的用戶模式分區(qū)并不大(一半不到),如圖:
這一分區(qū)的進程地址空間的范圍為:[0x00000000,?0x0000FFFF],總大小為64K,保留該分區(qū)的目的是為了幫助應用程序員捕獲對空指針的賦值。如malloc分配內(nèi)存失敗,就會返回NULL。
如果進程中的線程試圖訪問該分區(qū)內(nèi)的內(nèi)存地址,就會引發(fā)訪問違規(guī)。
在Windows中,所有的exe和動態(tài)鏈接庫都載入到這一區(qū)域。系統(tǒng)同時會把該進程可以訪問的所有內(nèi)存映射文件(后面會介紹)映射到這一分區(qū)。
進程無法通過指針來讀取、寫入、訪問其他進程的這一分區(qū),因此一個應用程序破壞另一個應用程序的可能性就非常小了,從而使整個系統(tǒng)更加堅固。
內(nèi)核模式分區(qū)是操作系統(tǒng)代碼的駐地。與線程調(diào)度、內(nèi)存管理、文件系統(tǒng)支持、網(wǎng)絡支持以及設(shè)備驅(qū)動程序相關(guān)的代碼都會載入到這一分區(qū)。該分區(qū)內(nèi)的代碼和數(shù)據(jù)被完全的保護起來了,如果一個應用程序試圖讀取或?qū)懭胛挥谶@一分區(qū)的內(nèi)存地址,會引發(fā)訪問違規(guī)。
駐留在這一分區(qū)內(nèi)的代碼為所有進程共有。
四、虛擬地址空間的使用
虛擬地址空間的使用涉及到3個概念:頁面大小、分配粒度、預定和調(diào)撥。
4.1 頁面大小
虛擬地址空間被分成以“頁面”為單位,因為硬件內(nèi)存管理單元是以頁面為粒度將虛擬地址轉(zhuǎn)譯成物理地址的。頁面的大小根據(jù)不同的CPU不而有所不同。x86和x64系統(tǒng)使用的頁面大小都是4KB,而IA-64系統(tǒng)使用的頁面大小是8KB。
IA-64操作系統(tǒng)只能在INTEL安騰系列處理器及AMD部分服務器處理器運行,所以主流市場并不常見
當應用程序在虛擬地址空間分配空間時,系統(tǒng)需要確保分配區(qū)域的大小正好是系統(tǒng)頁面大小的整數(shù)倍。
當應用程序在從虛擬地址空間分配空間時,系統(tǒng)會確保所有分配區(qū)域的起始地址都是分配粒度的整數(shù)倍。分配粒度的會根據(jù)不同的CPU平臺而有所不同,但目前所有的CPU平臺的分配粒度都是使用64KB。也就是說,分配的起始地址 = 64 * N。
通過Windows的GetSystemInfo函數(shù)也可以獲得此分配粒度值。
上面所說的分配粒度和頁面大小的限制,只是針對于“應用程序”,系統(tǒng)內(nèi)核自己不存在這樣的限制。
虛擬地址空間的使用分為2個步驟:
預定(reserve):告訴系統(tǒng)我們要從虛擬地址空間預定哪一塊區(qū)域,系統(tǒng)為我們保留這一塊區(qū)域。預定的局域的起始地址和大小遵循上面介紹的分配粒度和頁面大小的要求。因為預定的只是虛擬地址空間,不占用任何其他物理存儲器,所以沒有形成實質(zhì)的開銷。
調(diào)撥(commit):預定的區(qū)域還不能使用,我們還需要為預定的區(qū)域從頁交換文件中調(diào)撥存儲器,調(diào)撥之后我們才能使用該區(qū)域。
至于為什么要從頁交換文件中調(diào)撥存儲器??頁交換文件如何與物理內(nèi)存之間交互?下一篇文章《Windows內(nèi)存體系(2) – 虛擬內(nèi)存》會介紹。
windows
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。