1.物理地址編程
計算機系統的主存被組織成一個由M個連續的字節大小的單元組成的數組,每字節都有一個惟一的物理地址PA。數組
根據物理地址尋址的是物理尋址。2.虛擬地址緩存
虛擬存儲器被組織爲一個由存放在磁盤上的N個連續的字節大小的單元組成的數組。數據結構
使用虛擬尋址時,CPU經過生成一個虛擬地址VA來訪問主存,這個虛擬地址在被送到存儲器以前先轉換成適當的物理地址(這個過程叫作地址翻譯,相關硬件爲存儲器管理單元MMU)函數
1.地址空間工具
地址空間是一個非負整數地址的有序集合:{0,1,2,……}操作系統
2.線性地址空間翻譯
地址空間中的整數是連續的。3d
3.虛擬地址空間指針
CPU從一個有 N=2^n 個地址的地址空間中生成虛擬地址,這個地址空間成爲稱爲虛擬地址空間。
4.地址空間的大小
由表示最大地址所須要的位數來描述。
N=2^n:n位地址空間
主存中的每一個字節都有一個選自虛擬地址空間的虛擬地址和一個選自物理地址空間的物理地址。
虛擬存儲器——虛擬頁VP,每一個虛擬頁大小爲P=2^平字節
物理存儲器——物理頁PP,也叫頁幀,大小也爲P字節。
任意時刻,虛擬頁面的集合都被分爲三個不相交的子集:
頁表是一個數據結構,存放在物理存儲器中,將虛擬頁映射到物理頁。
1.若是設置了有效位:
地址字段表示DRAM中相應的物理頁的起始位置,這個物理頁中緩存了該虛擬頁
缺頁:就是指DRAM緩存不命中。
缺頁異常:會調用內核中的缺頁異常處理程序,選擇一個犧牲頁。
頁:虛擬存儲器的習慣說法,就是塊
交換=頁面調度:磁盤和存儲器之間傳送頁的活動
按需頁面調度:直到發生不命中時才換入頁面的策略,全部現代系統都使用這個。
1.當頁面命中時,CPU動做:
處理器生成虛擬地址,傳給MMU
MMU生成PTE地址,並從高速緩存/主存請求獲得他
高速緩存/主存向MMU返回PTE
MMU構造物理地址,並把它傳給高速緩存/主存
高速緩存/主存返回所請求的數據給處理器。
2.處理缺頁時:
處理器生成虛擬地址,傳給MMU
MMU生成PTE地址,並從高速緩存/主存請求獲得他
高速緩存/主存向MMU返回PTE
PTE中有效位爲0,觸發缺頁異常
肯定犧牲頁
調入新頁面,更新PTE
返回原來的進程,再次執行致使缺頁的指令,會命中
多級頁表——採用層次結構,用來壓縮頁表。
1.要求
處理任意請求序列 當即響應請求 只使用堆 對齊塊 不修改已分配的塊
2.目標:
最大化吞吐率(吞吐率:每一個單位時間裏完成的請求數) 最大化存儲器利用率——峯值利用率最大化
雖然有未使用的存儲器,可是不能用來知足分配請求時,發生這種現象。
1.內部碎片
發生在一個已分配塊比有效載荷大的時候
易於量化。2.外部碎片
發生在當空閒存儲器合計起來足夠知足一個分配請求,可是沒有一個單獨的空間塊足以處理這個請求時發生
難以量化,不可預測。
堆塊的格式:
由一個字的頭部,有效荷載,和可能的額外填充組成。
空閒塊經過頭部中的大小字段隱含地鏈接着,分配器能夠經過遍歷堆中全部的塊,從而間接地遍歷整個空閒塊的集合。
須要:特殊標記的結束塊。
系統對齊要求和分配器對塊格式的選擇會對分配器上的最小塊大小有強制的要求。
1.首次適配
從頭開始搜索空閒鏈表,選擇第一個合適的空閒塊2.下一次適配
從上一次搜索的結束位置開始搜索3.最佳適配
檢索每一個空閒塊,選擇適合所需請求大小的最小空閒塊
用到sbrk函數:
#include <unistd.h>
vid *sbrk(intptr_t incr);
成功則返回舊的brk指針,出錯爲-1
合併是針對於假碎片問題的,任何實際的分配器都必須合併相鄰的空閒塊。
隱式的,分配時間是塊總數的線性時間
可是顯式的,是空閒塊數量的線性時間。隱式——隱式空閒鏈表
顯式——雙向鏈表,有前驅和後繼,比頭部腳部好使。2.排序策略:
後進先出
按照地址順序維護
有兩種基本方法:
1.簡單分離存儲
每一個大小類的空閒鏈表包含大小相等的塊,每一個塊的大小就是這個大小類中最大元素的大小。
(1)操做
若是鏈表非空:分配其中第一塊的所有
若是鏈表爲空:分配器向操做系統請求一個固定大小的額外存儲器片,將這個片分紅大小相等的塊,而且鏈接起來成爲新的空閒鏈表。
(2)優缺點
優勢:時間快,開銷小
缺點:容易形成內部、外部碎片2.分離適配
每一個空閒鏈表是和一個大小類相關聯的,而且被組織成某種類型的顯示或隱式鏈表,每一個鏈表包含潛在的大小不一樣的塊,這些塊的大小是大小類的成員。
這種方法快速而且對存儲器使用頗有效率。
Mark&Sweep垃圾收集器
有兩個階段:
標記:標記出根節點的全部可達的和已分配的後繼
清除:釋放每一個未被標記的已分配塊。
相關函數:
ptr定義爲typedef void *ptr
ptr isPtr(ptr p):若是p指向一個已分配塊中的某個字,那麼就返回一個指向這個塊的起始位置的指針b,不然返回NULL int blockMarked(ptr b):若是已經標記了塊b,那麼就返回true int blockAllocated(ptr b):若是塊b是已分配的,那麼久返回ture void markBlock(ptr b):標記塊b int length(ptr b):返回塊b的以字爲單位的長度,不包括頭部 void unmarkBlock(ptr b):將塊b的狀態由已標記的改成未標記的 ptr nextBlock(ptr b):返回堆中塊b的後繼
1.間接引用壞指針
常見錯誤:
——scanf錯誤2.讀未初始化的存儲器
常見錯誤:
——假設堆存儲器被初始化爲03.容許棧緩衝區溢出
常見錯誤:
——緩衝區溢出錯誤4.假設指針和它們指向的對象是相同大小的
在遠處起做用action at distance10.引發存儲器泄露
對於最後一節C程序中常見的與存儲器有關的錯誤,看完以後就不由回想起本身在編程的時候遇到的相似的問題。每次遇到這種問題的解決的方法都是去百度,而後根據百度上你們五花八門的方法一個一個試,問題解決了就解決了,沒解決便手足無措,錯誤也不知道具體是因爲什麼緣由而致使的。看完這一節以後,有一種原來如此的感受,下次遇到問題就能夠嘗試本身解決了。