內存分配方式與內存分配算法算法
內存分配方式有兩種,連續內存分配方式和離散內存分配方式。不一樣的分配方式又有不一樣的分配算法。ide
內存分配算法,其實就是:有一大塊空閒的資源,如何合理地分配資源?內存分配的思想能夠用到不少其餘的領域。好比Java虛擬機是如何將內存分配與回收的?再好比文件系統是如何將磁盤塊分配與回收的?其本質就是如何把空閒的資源分配出去,分配以後又如何回收?目標就是分配快,回收也快,並且還不浪費。那麼,就須要根據資源的特色、以及應用場景作權衡從而選擇何種方式進行分配與回收。spa
①連續內存分配方式進程
1)固定分區分配內存
將內存劃分紅若干個固定大小的塊。將程序裝入塊中便可。內存劃分紅各個塊以後,塊大小再也不改變。固然,劃分塊的方式有:全部的塊大小相等;劃分的塊大小不相等。資源
這種方式,在實際的內存分配以前,就已經知道了全部的內存塊大小了。虛擬機
2)動態分區分配io
須要一個空閒表 或者 空閒鏈 來記錄目前系統中空間的內存區域。在內存分配時,須要查找空間表或空閒鏈找到一塊內存分配給當前進程。垃圾回收
動態分區分配算法:循環
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)分段存儲管理
與分頁比較類似,不介紹了。