物理內(nèi)存
物理內(nèi)存,取決于尋址空間和實際內(nèi)存條的大小
- 8086只有20根地址線,它的尋址空間是0-2^20,只有1M,插上128MB的內(nèi)存條它的物理內(nèi)存也只是1M
- 32位機器的尋址空間是0-2^32,最大支持4GB內(nèi)存,而插上2GB的內(nèi)存條則物理內(nèi)存為2G
直接使用物理內(nèi)存的弊端
進程空間不隔離,沒有權(quán)限保護
因為程序都是直接訪問物理內(nèi)存,所以一個進程可以修改其他進程的內(nèi)存數(shù)據(jù),甚至可以修改內(nèi)核地址空間中的數(shù)據(jù)
程序運行時候的地址不確定
一個程序想要訪問自己程序內(nèi)存的址0x00000000地址,但是在物理內(nèi)存上分配內(nèi)存是隨機的,所以訪問0x00000000可能不是自己的內(nèi)存區(qū)域
內(nèi)存利用率低
假設(shè)內(nèi)存是連續(xù)分配的(也就是程序在物理內(nèi)存上是連續(xù)的)
1.進程A進來,向os申請了200的內(nèi)存空間,于是os把0~199分配給A
2.進程B進來,向os申請了5的內(nèi)存空間,os把200~204分配給它
3.進程C進來,向os申請了100的內(nèi)存空間,os把205~304分配給它
4.這個時候進程B運行完了,把200~204還給os
但是很長時間以后,只要系統(tǒng)中的出現(xiàn)的進程的大小>5的話,200-204這段空間都不會被分配出去(只要A和C不退出)。過了一段更長的時間,內(nèi)存中就會出現(xiàn)許許多多200-204這樣不能被利用的碎片
虛擬地址空間
為了解決直接操作物理內(nèi)存帶來的問題,所以引入了虛擬地址空間,因為這個空間是虛擬的,所以可以無限大。
每個進程都可以有自己的虛擬地址空間
基本內(nèi)存管理(分段)
在虛擬地址空間和物理地址空間之間做一一映射,這里映射的是一片連續(xù)的物理內(nèi)存
- 虛擬內(nèi)存解決了運行時內(nèi)存地址不確定的問題
- 分段解決了內(nèi)存空間的隔離,因為程序操作的是虛擬內(nèi)存,而分段使得對應的物理內(nèi)存不會重疊
- 因為分段映射的是一段連續(xù)的物理內(nèi)存,所以沒有解決內(nèi)存利用率低的問題
實現(xiàn)分段的策略
固定分區(qū)
將內(nèi)存分為幾個固定的區(qū)域,每個區(qū)域的大小固定(通常不同),需要加載程序是選擇一個閑置且容量足夠大的分區(qū)進行加載

上面共享隊列的固定分區(qū)策略可能造成一個小程序占用一個大分區(qū)的情況,從而造成內(nèi)存里雖然有小分區(qū)閑置但無法加載大程序的情況??梢圆捎枚鄠€隊列,給每個分區(qū)一個隊列,程序按照大小排在相應的隊列里,如下圖所示,這時一種分開隊列的固定分區(qū)

這種方式也有缺點:如果還有空閑分區(qū),但等待的程序不在該分區(qū)的等待隊列上,就將造成有空間而不能運行程序的情況
非固定分區(qū)
非固定分區(qū)的思想在于除了劃分給OS的空間之外,其余的內(nèi)存空間是作為一個整體存在的。當一個程序需要占用內(nèi)存空間時,就在該片空間里面分出一個大小剛剛滿足程序所需的空間。再來一個程序時,則在剩下的空間里再這樣分出一塊來。在這種模式下,一個程序可以加載到任何地方,也可以和物理內(nèi)存一樣大。

- 程序運行時的內(nèi)存空間會增長,需要預留出增長空間
- 預留太多會造成浪費,太小可能造成程序無法運行或者發(fā)生分區(qū)交換
交換分區(qū)swap
因為系統(tǒng)分配給程序的空間分段映射的是一段連續(xù)的物理內(nèi)存,所以空間不夠時可以將程序倒到外置存儲中,再尋找足夠的內(nèi)存空間加載
- 因為每次空出來的內(nèi)存空間都是相對比較小的,所以多次交換之后內(nèi)存碎片會越來越多
- 交換過程涉及到外置存儲,速度比內(nèi)存低很多
- 單一程序不能超過物理內(nèi)存空間
雙基址
要運行兩個相同的程序,只是數(shù)據(jù)不一樣,那么我們可不可以進行指令的共享?可以!那么我們怎么使在共享的過程中不產(chǎn)生錯誤呢?那就是雙基址:給指令和數(shù)據(jù)各自配置基址。
其實就是將指令和數(shù)據(jù)分成不同的段
分頁
因為分段技術(shù)映射到物理內(nèi)存上是一段連續(xù)的空間,所以無可避免的會造成內(nèi)存利用率不高的問題
為了增加內(nèi)存的利用率,需要使用分頁技術(shù)
什么是分頁
將虛擬內(nèi)存空間和物理內(nèi)存空間皆劃分為大小相同的頁面,如4KB、8KB或16KB等,并以頁面作為內(nèi)存空間的最小分配單位,一個程序的一個頁面可以存放在任意一個物理頁面里。
虛擬地址的構(gòu)成與地址翻譯
在分頁系統(tǒng)中,一個程序的虛擬地址由頁面號和頁內(nèi)偏移值兩部分組成
32位尋址系統(tǒng)中,如果頁面大小為4k,則頁面號占20位,頁內(nèi)偏移值占12位

虛擬內(nèi)存頁到物理內(nèi)存頁的映射由內(nèi)存管理單元完成(MMU)

頁表的根本功能是提供從虛擬頁面到物理頁面的映射。因此,頁表的記錄條數(shù)與虛擬頁面數(shù)相同。此外,內(nèi)存管理單元依賴于頁表來進行一切與頁面有關(guān)的管理活動,這些活動包括判斷某一頁面號是否在內(nèi)存里,頁面是否受到保護,頁面是否非法空間等等,頁表是一個硬件數(shù)據(jù)結(jié)構(gòu)
分頁系統(tǒng)的優(yōu)點
- 分頁的大小比較小,不會產(chǎn)生外部碎片
- 一個進程占用的內(nèi)存空間可以不是連續(xù)的,并且一個進程的虛擬頁面在不需要的時候可以放在磁盤中
分頁系統(tǒng)的缺點
- 頁表大小很大
- 32位尋址4k大小的頁的頁表大小為2^20(頁數(shù))*4Byte(表項長度=20位頁號+12位控制位)=4MB
- 分頁系統(tǒng)存在的一個無法容忍,同時也是分頁系統(tǒng)無法解決的一個缺點就是:一個進程只能占有一個虛擬地址空間。在此種限制下,一個程序的大小至多只能和虛擬空間一樣大,其所有內(nèi)容都必須從這個共同的虛擬空間內(nèi)分配。
邏輯分段
邏輯分段將一個程序按邏輯關(guān)系分解為多個段
- 每個邏輯單元可單獨占用一個虛擬地址空間,這樣使得編寫程序的空間大為增長。
- 由于段式按邏輯關(guān)系劃分,因此共享起來十分方便。
- 對于空間稀疏的程序來說,分段管理將節(jié)省大量的空間。
重疊overlay
如果一個程序需要使用比物理內(nèi)存更大的內(nèi)存空間怎么辦?
此時,可以將程序按照功能分成一段一段功能相對完整的單元,一個單元執(zhí)行完成后再執(zhí)行下一個單元,這就是重疊(overlay)
相當于一列火車從上海到北京,不需要一整段完整的鐵軌,只需要兩段火車長度的鐵軌,不斷移動鐵軌,就可以讓火車一直往前開
段頁式
綜合了邏輯分段和分頁的優(yōu)點,將程序分為多個邏輯段,在每個段里面又進行分頁,即將分段和分頁組合起來使用。
采用多級頁表,頂級為段表,次級為頁表。由段號在段表里面獲得所應該使用的頁表,然后在該頁表里面查找物理頁面號

參考資料
操作系統(tǒng)核心原理-5.內(nèi)存管理(上):基本內(nèi)存管理
操作系統(tǒng)核心原理-5.內(nèi)存管理(中):分頁內(nèi)存管理
操作系統(tǒng)核心原理-5.內(nèi)存管理(下):段式內(nèi)存管理
基本內(nèi)存管理的簡單介紹