1. 程式人生 > >騰訊實習生面試--記憶體管理方法

騰訊實習生面試--記憶體管理方法

由於騰訊實習生面試的比較早,具體問題我也給忘了。但是我記得是一個關於作業系統記憶體分配方案的,當時關於作業系統之類的知識大部分都忘了。今天在這裡對作業系統中記憶體管理這一塊做一個總結。

1、記憶體管理的背景:

當前的計算機都是支援多個程序並行執行的,多個程序在單核CPU上以時間片為單位不斷的輪換執行。通常情況下,多個程序併發執行所需要的ROM數目要遠遠超過計算機的實際記憶體的。那麼CPU是如何做到所需的ROM數超過記憶體時,仍能夠正常執行呢?這就需要高效的記憶體管理技術。

也許是受“CPU在不同程序之間以時間片為單位高速切換來處理多個任務”這種方法的啟發,將這一原理應用到記憶體管理方面。

2、方法

現有兩種記憶體超載的處理方法:交換和虛擬記憶體。下面我們針對這兩種方法分別進行詳細說明。

2.1 交換

(1)什麼是交換技術?

把一個將要執行的程序(process)調入記憶體中執行一段時間後,再將其調出到本地磁碟。空閒程序主要都在本地磁碟中存放著,所以不執行的程序不會耗費計算機的記憶體資源。(將要執行程序調入記憶體中,執行一段時候在調回到磁碟中)。

(2)程序交換的例子


上圖是一個程序之間記憶體交換的例子。圖(a)中,橙色部分為記憶體中空閒部分。在圖(b)中,顯示當一個程序a被調入記憶體中進行執行時的狀態。圖(c)(d)顯示的是程序b、程序c調入記憶體中,記憶體的狀態。此時記憶體中共放了3個程序。當時如果想要放入程序d時,顯然剩餘的空閒記憶體已經不夠了。此時需要使用某個替換策略將某塊記憶體換出,換入。

注意:剛開始時程序a在記憶體中執行一段時間後被換出到本地磁碟,等一會a又被掉入記憶體。這兩次中a在記憶體中的位置時不同的,需要使用“重定位”技術才能夠保證a接著從上次停止的地方繼續往下執行。重定位技術要使用到兩個部件為“基址暫存器”和“界限暫存器”。

(3)記憶體緊縮技術

從最後一個圖(d)我們可以看到,記憶體中有兩個不連續的小空閒區,這種情況下無法在兩個小的空閒去執行一個程序,但是如果將這兩個小的空閒區連成一個大的空閒區就可以執行一個程序了。

將多個小的空閒區下移到放在一起構成一個大的空閒區,這種技術叫作“記憶體緊縮技術”。

(4)一個程序的記憶體佈局

在第二部分我們討論了多個程序在記憶體中的交換方式和佈局,在這裡我們對一個程序在記憶體中的情況進行討論。一個程序在執行過程中所佔用的記憶體可能會增加,因為會有新資料產生,新記憶體的申請。因此,一個程序除了程序的程式所佔的空間之外還要額外的空間來儲存程序執行過程中產生的資料。

所以所一個程序所佔的記憶體應該包括:堆區、棧區、全域性/靜態資料區、常量區、程式碼區。

Q:堆和棧上變數的區別表現在這幾方面:記憶體管理方式不同、記憶體增長方式的不同、碎片的區別、效率的不同

(5)空閒記憶體的管理方法(用於顯示當前記憶體的佈局)

點陣圖法:記憶體中每個儲存單位對應著點陣圖中的一個二進位制位,如果這個儲存單元被佔用,點陣圖中為1;如果這個儲存單元不被佔用,點陣圖中為0;

點陣圖的大小由總記憶體大小、每個儲存單元大小共同決定。

連結串列法:將一段連續的空閒區或者已分配區存放在連結串列的一個節點中。

struct LinkNode
{
     int startAddr;//起始地址
     int n;//所佔位元組數
     bool f;//標記空閒區或者被分配區
     LinkNode *next;//下一個節點的指標
};
使用LinkNode將當前程序所佔用的記憶體和空閒記憶體穿起來形成一個連結串列。

當新的程序來時,需要使用一定的記憶體分配策略給新程序分配記憶體。現有的記憶體分配策略有:

首次適配:每次都從連結串列頭部開始找一個能夠裝得下程序的空閒區;

下次適配:從上次結束的位置開始(不是每次從頭開始),找到能夠放得下程序的空閒區;

最佳適配:遍歷整個連結串列,找到一個恰好能夠放得下程序的空閒區;

最差適配:遍歷整個連結串列,將連結串列中最大空閒區分配給程序。如果沒有空閒區滿足,使用交換技術換出一個程序。

2.2 虛擬記憶體

在交換技術中用到的“重定位技術”是指:程序a在記憶體中執行一段時間後被換出到本地磁碟,一段時間後a又被調入記憶體,為了使程序a接著上次的位置繼續執行,要對a進行“重定位”。

(1)為什麼需要虛擬記憶體

交換技術是指將整個程序換入換出到磁碟,整個程序都需要在記憶體中才能夠執行。但是現實中,一個程式所需要的記憶體就可能大於實體記憶體,無法將整個程式都放入記憶體中,這時就需要“虛擬記憶體”技術。

(2)什麼是虛擬記憶體

虛擬記憶體的實現需要兩個手段“需要時載入”和“換入換出”。所謂“需要時載入”就是一個程式執行時,不需要將程式的所有資料都裝入實體記憶體中,只要將程式執行所需要的那部分放入記憶體中即可。從而可以執行所需記憶體比實體記憶體大的程式。當然實現虛擬記憶體還需要其他額外的技術。

所謂“換入換出”是指,當實體記憶體滿時,要將實體記憶體中不使用的頁面換出,然後將要執行的換入實體記憶體。

(3)分頁

1>邏輯地址到實體地址對映

虛擬地址空間大小:虛擬地址有nbit,那麼虛擬地址空間大小為2^nbit;

一個頁面的大小:一個記憶體單元大小,k bit,則一個頁面大小為為2^k bit;

頁號:邏輯地址中每個頁面會對應著一個頁號;

頁框號:將實體地址中每個單元進行編號,一個實體記憶體單元對應著一個頁框號;

頁表:頁號到頁框號的對映;如果一個頁號對應的頁框號不存在,就會引發缺頁中斷。

那麼這個程式可以分為2^n / 2 ^k 個頁面。

程式首先在虛擬記憶體中存放著,如果程式執行過程中需要某個頁面的話,首先會通過MMU看這一個頁面在不在實體記憶體中。如果在實體記憶體中,直接執行;如果通過MMU對映後發現不在實體記憶體中,產生缺頁中斷,需要將其調入記憶體中。調入之前會使用頁面置換演算法將實體記憶體中某個頁面換出,將要執行的放入實體記憶體中。

MMU(記憶體管理單元):MMU是記憶體管理單元,用於實現從虛擬空間的一個邏輯地址到實體記憶體中地址的對映;(ARP:IP地址---->MAC地址)

例子:

如果程式執行過程中需要執行邏輯地址a的那段程式,系統會通過MMU將邏輯地址a對映到實體記憶體中的一個實體地址b。如果對映成功,說明a已經被裝入記憶體,直接執行即可;如果發現a沒有被放入記憶體中,就會產生缺頁中斷,呼叫頁面置換演算法清除實體記憶體中的一個位置,並把a放入記憶體中並建立對映。

MMU中過程:邏輯地址a------>實體地址b

方法一:a/(2^k)是邏輯地址的頁號,a%(2^k)是頁面內的偏移。在頁表中使用頁號找到對應的頁框號,在於頁內偏移連線起來就是實體記憶體的地址。b = f(a/(2^k)) * 2^k + a%(2^k),其中f為頁表的對映。

方法二:將a用二進位制表示,高n-k位就是頁號對應的二進位制,低k位是在該頁面中的偏移。在頁表中根據頁號查詢到對應的頁框號,然後使用頁框號替換a中的高n-k位就是記憶體中的實體地址b。如果頁表中頁號對應的頁框號不存在,引發缺頁中斷。


注意:可以使用快表、多級頁表等策略加速邏輯地址到實體地址的對映;

每個邏輯地址分為頁號,頁內偏移。在頁表中根據頁號找到頁框號。

2> 頁面置換演算法

當想要使用某段程式時,MMU發現改程式不在實體記憶體中,此時引發缺頁中斷。系統會用某種策略從當前記憶體中去除一個,然後將其調入實體記憶體中。這時就需要頁面置換演算法。

FIFO:將最早放入實體記憶體中的頁面換出去;

LRU:將最近未使用時間最長的頁面置換出去;

(4)分段

Q:何為分段?

A:分頁中整個程式的邏輯地址是連續的(從0開始,線性增長,一直到程式結束),一個地址接著另一個地址。使用分頁的虛擬地址是一維的,每個頁面大小是固定的。

對於分段而言,將整個程式分為若干個段,每個段的大小是不同的。每個段是一個獨立的邏輯地址空間,每個段都是從0開始的線性地址,段與段之間互不影響。


上圖中我們將一個程序分為4個段,每個段大小都是不同的,每個段起始地址都是從0開始的。

Q:純分段的記憶體管理

A:類似於分頁記憶體管理,純分段記憶體管理是指程式執行時,會將整個段都裝入到記憶體中,這種方法顯然是抵消的。

Q:段頁式記憶體管理

A:在分段的基礎上,對每個段進行分頁。每個邏輯地址分為三部分:段號,段內頁號,頁內偏移。

首先根據段號去找對應的頁表,如果沒有找到這個頁表,產生一個段錯誤;如果找到,在頁表中根據頁號去找頁框號,然後在結合頁內偏移獲得實體地址。如果頁表中對應的頁號不存在,產生缺頁中斷。

Q:段頁式儲存管理地址對映過程

A:

1)程式執行時,從PCB中取出段表始址和段表長度,裝入段表暫存器。

2)由地址變換機構將邏輯地址自動分成段號、頁號和頁內地址。

3)將段號與段表長度進行比較,若段號大於或等於段表長度,則表示本次訪問的地址已超越程序的地址空間,產生越界中斷。

4)將段表始址與段號和段表項長度的乘積相加,便得到該段表項在段表中的位置。

5)取出段描述子得到該段的頁表始址和頁表長度。

6)將頁號與頁表長度進行比較,若頁號大於或等於頁表長度,則表示本次訪問的地址已超越程序的地址空間,產生越界中斷。

7)將頁表始址與頁號和頁表項長度的乘積相加,便得到該頁表項在頁表中的位置。

8)取出頁描述子得到該頁的物理塊號。

9)對該頁的存取控制進行檢查。

10)將物理塊號送入實體地址暫存器中,再將有效地址暫存器中的頁內地址直接送入實體地址暫存器的塊內地址欄位中,拼接得到實際的實體地址。

(5)分段與分頁有什麼區別?

原理:分頁是一維的,將整個程式看做一個整體,地址從0開始線性增長。每個部分都有一個地址,地址與地址之間是連續的。程式被放在若干大小相同的頁中,每個頁面的大小是相同的。

分段是二維的,是將整個程式分為若干個段,每個段的地址都是從0開始的,每個段的大小是不同的。段頁式記憶體管理中,會在對每個段進行分頁。

(1)頁是資訊的物理單位,分頁是為了實現非連續分配,以便解決記憶體碎片問題,或者說分頁是由於系統管理的需要.段是資訊的邏輯單位,它含有一組意義相對完整的資訊,分段的目的是為了更好地實現共享,滿足使用者的需要

(2)頁的大小固定,是由系統確定的,將邏輯地址劃分為頁號和頁內地址是由機器硬體實現的。而段的長度不是固定的,決定於使用者的程式長度,通常由編譯程式進行編譯時根據資訊的性質來劃分;

(3)分頁式儲存管理的作業地址空間是一維的,分段式儲存管理的作業管理地址空間是二維的;