記憶體應容納作業系統和各種使用者程序,因此應該盡可能有效地分配記憶體。
通常,我們需要將多個程序同時放在記憶體中。因此我們需要考慮,如何為輸入佇列中需要調入記憶體的程序分配記憶體空間。在採用連續記憶體分配時,每個程序位於乙個連續的記憶體區域,與包含下乙個程序的記憶體相連。
1. 最為簡單的記憶體分配方法之一,就是將記憶體分為多個固定大小的分割槽。每個分割槽可以只包含乙個程序。因此,多道程式的程度受限於分割槽數。如果使用這種多分割槽方法,那麼當乙個分割槽空閒時,可以從輸入佇列中選擇乙個程序,以調入空閒分割槽。當該程序終止時,它的分割槽可以用於其他程序。
這種方法最初為 ibmos/360 作業系統所使用,現在已不再使用。下面所描述的方法是固定分割槽方案的推廣(稱為 mvt),它主要用於批處理環境。這裡所描述的許多思想也可用於採用純分段記憶體管理的分時作業系統。
2. 對於可變分割槽方案,作業系統有乙個表,用於記錄哪些記憶體可用和哪些記憶體已用。開始,所有記憶體都可用於使用者程序,因此可以作為一大塊的可用記憶體,稱為塊。最後,正如將會看到的,記憶體有乙個集合,以包含各種大小的塊。
隨著程序進入系統,它們將被加入輸入佇列。作業系統根據所有程序的記憶體需求和現有可用記憶體的情況,決定哪些程序可分配記憶體。當程序分配到空間時,它就載入到記憶體,並開始競爭 cpu。當程序終止時,它將釋放記憶體,該記憶體可以被作業系統分配給輸入佇列內的其他程序。
任何時候,都有乙個可用塊大小的列表和乙個輸入佇列。作業系統根據排程演算法來對輸入佇列進行排序。記憶體不斷地分配給程序,直到下乙個程序的記憶體需求不能滿足為止,這時沒有足夠大的可用塊來載入程序。作業系統可以等到有足夠大的空間,或者可以往下掃瞄輸入佇列,以確定是否有其他記憶體需求較小的程序可以被滿足。
通常,如上所述,可用的記憶體塊為分散在記憶體裡的不同大小的塊的集合。當新程序需 要記憶體時,系統為該程序查詢足夠大的塊。如果塊太大,那麼就分為兩塊:一塊分配給新程序,另一塊還回到塊集合。當程序終止時,它將釋放記憶體,該記憶體將還給塊的集合。如果新塊與其他塊相鄰,那麼將這些塊合併成大塊。這時,系統可以檢查,是否有程序在等待記憶體空間,以及新合併的記憶體空間是否滿足等待程序等。
這種方法是通用動態儲存分配問題(根據一組空閒塊來分配大小為 n 的請求)的乙個特例。這個問題有許多解決方法。
從一組可用塊中選擇乙個空閒塊的最為常用方法包括:首次適應、最優適應及最差適應:
模擬結果顯示,首次適應和最優適應在執行時間和利用空間方面都好於最差適應。首次適應和最優適應在利用空間方面難分伯仲,但是首次適應要更快些。
用於記憶體分配的首次適應和最優適應演算法都有外部碎片的問題。
隨著程序載入到記憶體和從記憶體退出,空閒記憶體空間被分為小的片段。當總的可用記憶體之和可以滿足請求但並不連續時,這就出現了外部碎片問題:儲存被分成了大量的小塊,這個問題可能很嚴重。
在最壞情況下,每兩個程序之間就有空閒(或浪費的)塊。如果這些記憶體是一整塊,那麼可能可以再執行多個程序。
選擇首次適應或者最優適應,可能會影響碎片的數量。(對一些系統來說,首次適應更好;對另一些系統,最優適應更好)。另一因素是從空閒塊的哪端開始分配。(哪個是剩餘的塊,是上面的還是下面的?)不管使用哪種演算法,外部碎片始終是個問題。
根據記憶體空間總的大小和平均程序大小的不同,外部碎片問題或許次要或許重要。例如,採用首次適應方法的統計說明,不管使用什麼優化,假定有 n 個可分配塊,那麼可能有 0.5n 個塊為外部碎片。即 1/3 的記憶體可能不能使用。這一特性稱為 50%規則。
記憶體碎片可以是內部的,也可以是外部的。假設有乙個 18 464 位元組大小的孔,並採用 多分割槽分配方案。假設有乙個程序需要 18 462 位元組。如果只能分配所要求的塊,那麼還剩下乙個 2 位元組的塊。維護這一小塊的開銷要比塊本身大很多。
因此,通常按固定大小的塊為單位(而不是位元組)來分配記憶體。採用這種方案,程序所分配的記憶體可能比所需的要大。這兩個數字之差稱為內部碎片,這部分內存在分割槽內部,但又不能用。
外部碎片問題的一種解決方法是緊縮。它的目的是移動記憶體內容,以便將所有空閒空間合併成一整塊。然而,緊縮並非總是可能的。如果重定位是靜態的,並且在彙編時或載入時進行的,那麼就不能緊縮。只有重定位是動態的,並且在執行時進行的,才可採用緊縮。
如果位址被動態重定位,可以首先移動程式和資料,然後再根據新基位址的值來改變基位址暫存器。如果能採用緊縮,那麼還要評估開銷。最簡單的合併演算法是簡單地將所有程序移到記憶體的一端,而將所有的塊移到記憶體的另一端,從而生成乙個大的空閒塊。這種方案比較昂貴。
外部碎片化問題的另乙個可能的解決方案是,允許程序的邏輯位址空間是不連續的,這樣,只要有物理記憶體可用,就允許為程序分配記憶體。有兩種互補的技術可以實現這個解決方案:分段和分頁。這兩個技術也可以組合起來。
碎片是乙個常見問題,當需要管理資料塊時它就可能出現。
程式設計師通常願意將記憶體看作一組不同長度的段,這些段之間並沒有一定的順序(圖 1)。
當編寫程式時,程式設計師認為它是由主程式加上一組方法、過程或函式所構成的。它還可以包括各種資料結構,例如物件、陣列、堆疊、變數等。每個模組或資料元素通過名稱來引用。程式設計師會說「堆疊」、「數學庫」和「主程式」等,而並不關心這些元素所在記憶體的位置,及他不關心堆疊是放在函式 sqrt() 之前還是之後。
分段就是支援這種使用者檢視的記憶體管理方案。邏輯位址空間是由一組段構成。每個段都有名稱和長度。位址指定了段名稱和段內偏移。
分段允許程序的實體地址空間是非連續的。分頁是提供這種優勢的另一種記憶體管理方案。然而,分頁避免了外部碎片和緊縮,而分段不可以。
不僅如此,分頁還避免了將不同大小的記憶體塊匹配到交換空間的問題,在分頁引入之前採用的記憶體管理方案都有這個問題。由於比早期方法更加優越,各種形式的分頁為大多數作業系統採用,包括大型機的和智慧型手機的作業系統。實現分頁需要作業系統和計算機硬體的協作。
實現分頁的基本方法涉及將物理記憶體分為固定大小的塊,稱為幀或頁幀,而將邏輯記憶體也分為同樣大小的塊,稱為頁或頁面。當需要執行乙個程序時,它的頁從檔案系統或備份儲存等處,載入到記憶體的可用幀。備份儲存劃分為固定大小的塊,它與單個記憶體幀或與多個記憶體幀(簇)的大小一樣。
分頁優點之一是可以共享公共**。對於分時環境,這種考慮特別重要。
分頁,分段等,所有這些策略都有相同的目標,就是同時將多個程序儲存在記憶體中,以便允許多道程式。然而,這些策略都傾向於要求每個程序在執行之前應完全處於記憶體中。
虛擬記憶體技術允許執行程序不必完全處於記憶體。這種方案的乙個主要優點就是,程式可以大於物理記憶體。此外,虛擬記憶體將記憶體抽象成乙個巨大的、統一的儲存陣列,進而實現了使用者看到的邏輯記憶體與物理記憶體的分離。這種技術使得程式設計師不再擔憂記憶體容量的限制。
虛擬記憶體還允許程序輕鬆共享檔案和實現共享記憶體。此外,它為建立程序提供了有效的機制。然而,虛擬記憶體的實現並不容易,並且使用不當還可能會大大降低效能。
記憶體管理演算法的實現有乙個基本要求,就是執行的指令應處於物理記憶體中。滿足這一要求的第一種方法是,將整個邏輯位址空間置於物理記憶體中。動態載入可以幫助緩解這種限制,但它通常需要特殊的預防措施和程式設計師的額外工作。
指令應處於物理記憶體以便執行的要求,似乎是必要的和合理的,但它也是有缺點的,因為它將程式的大小限制為物理記憶體的大小。事實上,通過實際程式的研究會發現,在許多情況下並不需要將整個程式置於記憶體中(見下例)。
例如,分析以下內容:
即使在需要整個程式的情況下,也可能並不同時需要整個程式。分段能夠執行只有部分處於記憶體的程式,可以帶來許多好處:
虛擬記憶體將使用者邏輯記憶體與物理記憶體分開。這在現有物理記憶體有限的情況下,為程式設計師提供了巨大的虛擬記憶體(如下圖所示)。
因此,虛擬記憶體使得程式設計更加容易,因為程式設計師不再需要擔心有限的物理記憶體空間,只需要關注所要解決的問題。
除了將邏輯記憶體與物理記憶體分開外,虛擬記憶體允許檔案和記憶體通過共享頁而為多個程序所共享。這帶來了以下好處:
通過將共享物件對映到虛擬位址空間中,系統庫可以為多個程序所共享類似地,虛擬記憶體允許程序共享記憶體。程序之間可以通過使用共享記憶體來進行通訊。虛擬記憶體允許乙個程序建立乙個記憶體區域,以便與其他程序共享。共享這個記憶體區域的程序認為,它是其虛擬位址空間的一部分,而事實上這部分是共享的,如圖 3 所示。
當通過系統呼叫 fork() 建立程序時,可以共享頁面,從而加快程序建立。
記憶體分段 記憶體分頁 虛擬記憶體
程式通過鏈結器,多個檔案合併成乙個最終可執行檔案。可執行程式載入後占用的記憶體空間應該是連續的,因為執行指令的時候,程式計數器是順序地一條一條指令執行下去。這也就意味著,這一條條指令需要連續地儲存在一起。我們電腦肯定是要執行好多個程式的,在記憶體裡面肯定占用多個連續的分段,但是假如其中乙個程式退出,...
記憶體分配 分頁 分段
關於計算機記憶體分配,主要有兩種 連續記憶體分配和非聯絡記憶體分配。需要注意的是,這是作業系統級別的,而堆與棧的記憶體分配,是屬於編譯器級別的,具體可以參考另一篇筆記 連續記憶體分配是指為乙個程式分配位址連續的一段記憶體,當出現許多程式時,由於程式大小不一必然會出現許多的記憶體碎片,無法充分發揮出所...
記憶體離散分配 分頁 分段
基本分頁儲存管理方式 本部分討論不具備對換功能的純分頁模式,作業執行需要全部裝入記憶體。離散分配記憶體 作業規定大小劃分成小份 記憶體也按同樣大小劃分成小份 作業的任一小份可分散放入記憶體任意未使用的小份 分頁方式下,記憶體的使用率高,浪費少。但不是絕對沒有碎片 程序的最後一頁不總是能佔滿乙個物理塊...