虛擬存儲系統是指什么 虛擬存儲( 五 )


下次適配:每次從上次查詢結束的地方開始搜索,直到遇到合適的空空閑塊 。這種策略通常比第一種適應更有效,但是存儲器利用率低得多 。
最佳適應:檢查每個空空閑塊,并選擇適合所需請求大小的最小空空閑塊 。最佳匹配的內存利用率是三種策略中最高的,但是它需要對堆進行徹底的搜索 。
搜索鏈表的效率是線性的 。為了減少分配請求匹配空空閑塊的時間,分配器通常采用隔離存儲的策略,即維護多個空空閑鏈表,其中每個鏈表的塊大小大致相等 。
一個簡單的分離存儲策略:分配器維護一個空空閑鏈表數組,然后把所有可能的塊劃分成一些等價的類(也叫大小類),每個大小類代表一個空空閑鏈表,每個大小類的空空閑鏈表包含大小相等的塊,每個塊的大小在這個大小類中 。
當有分配請求時,我們檢查相應的空空閑鏈表 。如果鏈表不是空,那么分配第一個塊的全部 。如果鏈表是空,分配器向操作系統請求一個固定大小的額外內存片,將這個片分成大小相等的塊,然后將這些塊鏈接起來,形成一個新的空空閑鏈表 。
要釋放一個塊,分配器只需將該塊插入相應的空空閑鏈表的頭部 。
垃圾回收編寫C程序時,一般只能顯式分配和釋放堆中的內存(malloc()和free()) 。程序員不僅需要分配內存,還需要負責內存的釋放 。
很多現代編程語言都內置了自動內存管理機制(C/C++也可以通過引入自動內存管理庫來實現自動內存管理) 。所謂自動內存管理,就是自動判斷不再需要的堆內存(稱為垃圾內存),然后自動釋放垃圾內存 。
自動內存管理的實現是垃圾收集器,垃圾收集器是一個動態內存分配器,它會自動釋放應用程序不再需要的已分配塊 。
垃圾收集器通常采用以下兩種策略之一來確定堆內存是否為垃圾內存:
引用計數器:在數據的物理空空間增加一個計數器 。當有其他數據與之相關(引用)時,計數器加1,否則減1 。通過定期檢查計數器的值,只要是0,就認為是垃圾內存,可以釋放它占用的分配塊 。使用基準計數器,實現簡單直接,但缺點也很明顯 。它不能回收被循環引用的兩個對象(假設有對象A和對象B,相互引用,但實際上對象A和對象B都是無用對象) 。
可達性分析:垃圾收集器將堆內存看作一個有向圖,然后選擇一組根節點(比如在Java中,一般是類加載器、全局變量、運行時常量池中的引用類型變量等 。),并且根節點必須是足夠“活躍”的對象 。然后計算根節點集的可達路徑 。只要從根節點不可達的節點都被視為垃圾內存 。
有如下幾種垃圾收集器回收算法:
標記-清除:算法分為兩個階段:標記和掃描 。首先標記所有需要回收的對象,然后在標記完成后統一回收所有被標記的對象 。Mark-clear算法實現簡單,但是效率不高,而且會產生大量的內存碎片 。
標記-排序:標記-排序算法與標記-清除算法基本相同,只是下一步不是直接清理可回收對象,而是將所有活對象移到一端,然后直接清理邊界外的內存 。
復制:將程序擁有的內存空分成兩個大小相等的塊,每次只使用其中一個 。當這塊內存用完時,將幸存的對象復制到另一塊內存中,然后清理已用的內存空 。這種方法不需要考慮內存碎片的問題,但是內存利用率很低 。這個比例不是絕對的 。比如為了避免浪費,HotSpot虛擬機將內存分為Eden空和兩個幸存者空,每次只使用Eden和一個幸存者 ?;厥諘r,將伊甸園和幸存者中幸存的對象一次性復制到另一個幸存者空房間,然后將剛剛使用的伊甸園和幸存者空之間的房間清理干凈 。熱點虛擬機中Eden和Survivor的默認比例是8: 1,只有10%的內存空會被浪費 。
生成:生成算法根據對象生命周期的不同,將內存劃分為多個塊,以便針對不同的年齡采用不同的回收算法 。一般分為新生代和舊時代 。新生代存儲存活率低的對象,可以使用復制算法 。老年儲存存活率高的物件 。如果使用復制算法,內存空空間將不夠用,因此必須使用標記清除或標記排序算法 。
摘要虛擬內存是內存的抽象 。支持虛擬內存的CPU需要通過虛擬尋址來引用內存中的數據 。CPU加載一個虛擬地址,然后將其發送到MMU進行地址轉換 。地址翻譯需要硬件和操作系統的密切配合,MMU通過頁表的方式獲取物理地址 。
首先,MMU將虛擬地址發送到TLB以獲得PTE(根據VPN尋址) 。
如果PTE恰好緩存在TLB,它將被返回給MMU,否則MMU需要從緩存/內存中獲取PTE,然后將緩存更新到TLB 。

推薦閱讀