虛擬存儲器的三個重要能力:linux
它將主存當作是一個存儲在磁盤上的地址空間的高速緩存,在主存中只保存活動區域,並根據須要在磁盤和主存之間來回傳送數據,經過這種方式,高效的使用了主存。
算法
它爲每一個進程提供了一致的地址空間,從而簡化了存儲器管理
數組
它保護了每一個進程的地址空間不被其餘進程破壞。
緩存
計算機系統的主存被組織成一個由M個連續的字節大小的單元組成的數組。ruby
每一個字節都有惟一的物理地址。數據結構
第一個字節的地址爲0,接下來的字節地址爲1,在下一個爲2,依次類推。函數
給定這種簡單的結構,CPU訪問存儲器的最天然的方式就是使用物理地址。咱們把這種方式稱爲物理尋址。工具
現代處理器使用的是一種稱爲虛擬尋址的尋址形式。使用這虛擬尋址時,CPU經過生成一個虛擬地址來訪問主存,這個虛擬地址再被送到存儲器以前先轉換成適當的物理地址。spa
地址空間是一個非負整數地址的有序集合:{一、二、3.....}操作系統
線性地址空間:地址空間的整數是連續的。
虛擬地址空間:CPU從一個有 N=2^n 個地址的地址空間中生成虛擬地址,這個地址空間成爲稱爲虛擬地址空間。
物理地址空間:與系統中的物理存儲器的M個字節相對應{1,2,3.....,M-1}
1)未分配的:VM系統還沒分配/建立的頁,不佔用任何磁盤空間。
2)緩存的:當前緩存在物理存儲器中的已分配頁
3)未緩存的:沒有緩存在物理存儲器中的已分配頁
用術語DRAM緩存來表示虛擬存儲器系統的緩存,它在主存中緩存虛擬頁。
不命中處罰很大,由於大的不命中處罰和訪問第一字節的開銷,虛擬頁每每很大。
緩存是全相聯的——任何虛擬頁均可以放在任何的物理頁中。
不命中時的替換策略也很重要,由於替換錯了虛擬頁的處罰也很是之高。老是對磁盤訪問時間很長。替換算法精密,老是使用寫回而不是直寫。
頁表:是一個數據結構,存放在物理存儲器中,將虛擬頁映射到物理頁,就是一個頁表條目的數組。
頁表組成:有效位+n位地址字段。
缺頁:就是指DRAM緩存不命中。
缺頁異常:會調用內核中的缺頁異常處理程序,選擇一個犧牲頁。
變換/頁面調度:在磁盤和存儲器之間傳送頁的活動。
局部性:局部性原則保證了在任意時刻,程序將每每在一個較小的活動頁面集合上工做,這個集合叫作工做集或者常駐集。
若是工做集的大小超出了物理存儲器的大小,那麼程序將產生一種不幸的狀態,叫作顛簸。
1)簡化連接:獨立的地址空間容許每一個進程的存儲器映像使用相同的基本格式,而無論代碼和數據實際存放在物理存儲器的何處。
2) 簡化加載:虛擬存儲器使得容易想存儲器中加載可執行文件和共享文件對象。
3)簡化共享:獨立地址空間爲操做系統提供了一個管理用戶進程和操做系統自身之間共享的一致機制。
4)簡化存儲器分配:虛擬存儲器爲向用戶進程提供一個簡單的分配額外存儲器的機制。
任何現代計算機系統必須爲操做系統提供手段來控制對存儲器系統的訪問。
地址翻譯機制以一種天然的方式擴展到提供更好的訪問控制。每次CPU生成一個地址時,地址翻譯硬件都會讀一個PTE,因此經過在PTE上添加一些額外的許可位來控制對一個虛擬頁面內容的訪問十分簡單。
SUP:表示進程是否必須運行在內核模式下才能訪問該頁.
READ和WRITE:分別表示對頁面的讀寫訪問控制。
形式上來講,地址翻譯是一個N元素的虛擬地址空間(VAS)中的元素和一個M元素的物理地址空間(PAS)中元素之間的映射:MAP:VAS->PAS U ∅
MAP = A' :若是虛擬地址A處的數據在PAS的物理地址A'處。
MAP = ∅ :若是虛擬地址A處的數據不在物理存儲器中。
1)處理器生成虛擬地址,傳給MMU。
2)MMU生成PTE地址,並從高速緩存/主存請求獲得他。
3)高速緩存/主存向MMU返回PTE。
4)MMU構造物理地址,並把它傳給高速緩存/主存。
5)高速緩存/主存返回所請求的數據給處理器。
1)處理器生成虛擬地址,傳給MMU。
2)MMU生成PTE地址,並從高速緩存/主存請求獲得他。
3)高速緩存/主存向MMU返回PTE。
4)PTE中有效位爲0,觸發缺頁異常。
5)肯定犧牲頁。
6)調入新頁面,更新PTE。
7)返回原來的進程,再次執行致使缺頁的指令,會命中。
存儲器是按字節尋址的。
存儲器訪問是針對1字節的字的(不是4字節的字)。
虛擬地址是14位長的(n=14)。
物理地址是12位長的(m=12)。
頁面大小是64字節(p=64)。
TLB是四路組相聯的,總共有16個條目
L1 d-cache 是物理尋址、直接映射的,行大小爲4字節,而總共有16個組。
一個運行Linux的Intel Core i7是基於Nehalem微體系結構的。雖然Nehalem設計容許徹底的64位虛擬和物理地址空間,而如今以及可預見的將來的Core i7實現支持48位(256TB)虛擬地址空間和52位(4PB)物理地址空間,還有一個兼容模式,支持32位(4GB)虛擬和物理地址空間。
處理器包:包括四個核、一個大的全部核共享的L3高速緩存,以及一個DDR3存儲器控制器。
linux將虛擬存儲器組織成一些區域(也叫作段)的集合。一個區域就是已經存在着的(已分配的)虛擬存儲器的連續片,這些頁是以某種方式相關聯的。代碼段、數據段、堆、共享庫段,以及用戶棧都是不一樣的區域。
存儲器映器:指Linux經過將一個虛擬存儲器區域與一個磁盤上的對象關聯起來,以初始化這個虛擬存儲器區域的內容的過程。
共享對象:共享對象對於全部把它映射到本身的虛擬存儲器進程來講都是可見的。即便映射到多個共享區域,物理存儲器中也只須要存放共享對象的一個拷貝。
私有對象:私有對象運用的技術:寫時拷貝,在物理存儲器中只保存有私有對象的一份拷貝。
mmap函數要求內核建立一個新的虛擬存儲器區域
PROT_EXEC:這個區域的頁面由能夠被CPU執行的指令組成。
PROT_READ:這個區域的頁面可讀。
PROT_WRITE:這個區域的頁面可寫。
PROT_NONE:這個區域的頁面不能被訪問。
堆:一個請求二進制0的區域,緊接在未初始化的bss區域後開始,並向上(更高的地址)生長。有一個變量brk指向堆的頂部。
顯式分配器:要求應用顯示地釋聽任何已分配的塊。
隱式分配器:要求分配器檢測一個已分配塊什麼時候再也不被程序所使用,那麼就釋放這個塊。隱式分配器也叫作垃圾收集器,而自動釋放未使用的已分配的塊的過程叫作垃圾收集。
malloc和free函數:
程序經過調用malloc函數來從堆中分配塊。
#include <stdlib.h>
void *malloc(size_t size)
成功返回指針,指向大小至少爲size字節的存儲器塊,失敗返回NULL
這個塊會爲可能包含在這個塊內的任何數據對象類型作對齊。
還能夠用sbrk函數:
#include <unistd.h>
void *sbrk(intptr_t incr);
返回:若成功則爲舊的brk指針,若出錯則爲-1.
程序經過調用free函數來釋放已分配的堆塊:
#include <stdlib.h>
void free(void *ptr);
返回:無
ptr參數必須指向一個從malloc、calloc或者realloc得到的已分配塊的起始位置。
若是不是,那麼free的行爲就是未定義的。
要求:
a.處理任意請求序列
b.當即響應請求
c.只使用堆
d.對齊塊
e.不修改已分配的塊
目標:
a.最大化吞吐率
b.最大化存儲器利用率——峯值利用率最大化
void garbage()
{
int *p = (int *)Malloc(15213)
return;
}
是一種動態存儲分配器,它自動釋放程序再也不須要的已分配塊。這些塊稱爲垃圾。自動回收堆存儲的過程叫作垃圾收集。
在對Mark&Sweep的描述中使用下列函數:其中ptr定義爲typedef void *ptr
ptr isPtr(ptr p):若是p指向一個已分配塊中的某個字,那麼就返回一個指向這個塊起始位置的指針b,不然返回NULL。
int blockMarked(ptr b):若是已經標記了塊b,就返回true。
int blockAllocated(ptr b):若是塊b是已分配的,就返回true。
void markBlock(ptr b):標記塊b。
int length(ptr b):返回塊b的以字爲單位的長度(不包括頭部)。
void unmarkBlock(ptr b):將塊b的狀態由已標記的改成未標記的。
ptr nextBlock(ptr b):返回堆中塊b的後繼。
《深刻理解計算機操做系統》