內存分配與內存管理的一些理解


內存分配方式與內存分配算法

內存分配方式有兩種,連續內存分配方式和離散內存分配方式。不同的分配方式又有不同的分配算法。

內存分配算法,其實就是:有一大塊空閑的資源,如何合理地分配資源?內存分配的思想可以用到很多其他的領域。比如Java虛擬機是如何將內存分配與回收的?再比如文件系統是如何將磁盤塊分配與回收的?其本質就是如何把空閑的資源分配出去,分配之后又如何回收?目標就是分配快,回收也快,而且還不浪費。那么,就需要根據資源的特點、以及應用場景做權衡從而選擇何種方式進行分配與回收。

 

①連續內存分配方式

1)固定分區分配

將內存划分成若干個固定大小的塊。將程序裝入塊中即可。內存划分成各個塊之后,塊大小不再改變。當然,划分塊的方式有:所有的塊大小相等;划分的塊大小不相等。

這種方式,在實際的內存分配之前,就已經知道了所有的內存塊大小了。

 

2)動態分區分配

需要一個空閑表 或者 空閑鏈 來記錄目前系統中空間的內存區域。在內存分配時,需要查找空間表或空閑鏈找到一塊內存分配給當前進程。

 

動態分區分配算法:

a)首次適應法

b)循環首次適應法

c)最佳適應法

d)最壞適應法

e)快速適應法

 

3)可重定位分區分配

說白了,就是增加了內存移動的功能。由於若干次內存分配與回收之后,各個空閑的內存塊不連續了。通過“重定位”,將已經分配的內存“緊湊”在一塊(就類似於JVM垃圾回收中的復制算法)從而空出一大塊空閑的內存出來。

”緊湊“是需要開銷的,比如需要重新計算 地址,這也為什么JVM垃圾回收會導致STW的原因。

而離散分配方式--不管是分頁還是分段,都是直接將程序放到各個離散的頁中。從而就不存在“緊湊”一說了。

 

連續內存分配方式涉及兩種操作:內存分配操作 和 內存回收操作

 

②離散內存分配方式

內存資源是有限的,程序要運行,必須得加載到內存。如果內存已經滿了,而現在又有新的程序要運行,怎么辦?---SWAP

把當前不用的程序(數據)先換出內存,從而就有空間 加載當前需要運行的程序的一部分數據進入內存,這樣大大提高了內存的利用率。

由於牽涉到換入與換出,前面的連續內存分配方式就有點不適用了。因為,最明顯的一個問題:對於連續內存分配方式,究竟換出哪部分數據呢?

而這種只裝入部分"數據"就可以使程序運行的機制,就是虛擬存儲器的本質。

 

1)分頁存儲管理

將進程的邏輯地址空間分成若干大小相等的頁面;同時,也將物理內存分成相等大小的頁面(稱為塊或frame)。在為進程分配內存時,以塊為單位將進程的若干頁 可以 裝入到內存中多個不鄰接的物理塊中。

從上可以看出:“離散” 體現在:進程在內存中分配的空間(物理塊)是不連續的。而對於連續分配方式,進程在內存的分配的空間是連續的。

現在考慮32位系統,每個物理塊的大小為4KB。如何把邏輯地址 轉換成 物理地址?

對每個進程而言,都有着自己的頁表。頁表的本質就是邏輯地址到物理地址的映射。

分頁存儲中的邏輯地址的結構如下:

1)由於進程的邏輯頁面大小與物理塊(頁幀)大小相同,故都為4K,因此需要12個位表示4K的大小(2^12=4K),即圖中的【0-11】

2)【12-31】表示的是頁號。一共有20個位表示頁號,也即:對於一個進程而言,一共可以有1M(2^20=1M)個頁。

3)每個進程的邏輯地址空間范圍為0-2^32-1,因為:每個頁大小為4K,一共有1M個頁。故進程可用的邏輯空間為2^32B

 

邏輯地址到物理地址的轉換需要用到頁表。具體細節是有一個“地址變換機構”,它有一個寄存器保存頁表在內存的起始地址 以及 頁表的長度

上面提到,一個進程最多可以有1M個頁,故頁表就有1M個頁表項。假設每個頁表項只有1B,那頁表的大小也有1MB,所以:一般而言,頁表也是很大的,不能全放在寄存器中,故頁表也是存儲在內存中的。(有些機器有“快表”,快表就是一個寄存器,它保存了頁表中的部分表項);其次,也可以使用多級頁表以解決單個頁表太大的問題。

那現在給定一個邏輯地址,怎么知道其物理地址呢?

①將【12-31】位的頁號與 頁表的長度比較。頁號不能大於頁表長度,否則越界。

②根據頁號 找到 該頁號所在的頁表項,即該頁號對應着哪個頁表項。因為,頁表項里面就存放着物理地址。

那如何查找頁表項呢?將頁號乘以頁表項的長度(每個頁表項,其實就是一個邏輯的頁 到 物理頁 的映射信息),就知道了該邏輯頁對應着哪個頁表項(根據頁號匹配頁表項一般是由硬件完成的)

然后,正如前面提到,頁表也是保存在內存中的,故需要頁表的內存始址(這是也為什么地址變換機構 保存 頁表在內存的起始地址的原因),將頁表始址 與 上面的乘積相加,就得到了該邏輯頁對應的頁表項的物理地址。讀這個頁表項的物理地址中的內容,就知道了該邏輯頁對應的物理塊地址(物理地址)。從而,就完成了邏輯地址到物理地址的轉換。

從上面可以看出,CPU每存取一個數據時,需要兩次訪問主存。一次是訪問頁表項的物理地址,得到了數據的物理塊地址。第二次拿着物理塊地址去取數據。

在分頁存儲管理方式下:由於取一個數據,需要二次訪存,CPU處理速度降低了一半,正由於這個原因:引入了“快表”(又稱TLB(Translation Lookaside Buffer)),快表是個寄存器,用來保存那些當前訪問過的頁表項。從而,讀頁表項時,不需要再訪存了,而是直接從寄存器中讀取。

 

虛擬存儲器

談到虛擬存儲器,總是說它從邏輯上擴充了內存的容量,why?

內存是有限的,作業初始時保存在磁盤上的,如果要運行,必須得將相應的程序(數據)加載到內存中。那如果要運行的作業特別多,無法一下子裝入內存,怎么辦?

一種方式是加內存條,這是從物理上擴充內存的容量。

另一種方式是:先把作業的一部分程序(數據)裝入內存,先讓它運行着,運行過程中發現: 咦,我還需要其他的數據,而這些數據還未裝入內存,因此就產生中斷(缺頁中斷)再將數據加載到內存。

采用這種方式,系統一次就可以將很多作業裝入內存運行了。這時,從物理上看,內存還是原來的大小,但是它能運行的作業多了,因此說從邏輯上擴充了內存。

將虛擬存儲器這種思想與分頁存儲管理結合,一次只將作業的部分頁面加載到內存中,形成了一個強大的內存分配與管理系統了。引入了虛擬存儲器,同樣需要有頁表,記錄邏輯地址到物理地址的映射,只不過此時的頁表更復雜了,因為,有些頁可能還在磁盤上。;還需要有缺頁中斷處理機構,因為畢竟只將一部分數據裝入內存,會引起缺頁中斷嘛,就需要處理中斷嘛;還需要地址變換機構,這里的地址變換機構功能更多,因為需要處理中斷情況下的地址變換。

 

2)分段存儲管理

與分頁比較相似,不介紹了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM