2022年了,我不允許還有人不懂作業系統——記憶體管理
作業系統記憶體管理:總的來說,作業系統記憶體管理包括物理記憶體管理和虛擬記憶體管理。
物理記憶體管理:
包括程式裝入等概念、交換技術、連續分配管理方式和非連續分配管理方式(分頁、分段、段頁式)。
虛擬記憶體管理:
虛擬記憶體管理包括虛擬記憶體概念、請求分頁管理方式、頁面置換演算法、頁面分配策略、工作集和抖動。
這個系列主要使用linux記憶體管理來具體說明:linux記憶體管理
一、 計算機的儲存體系
記憶體是計算機很重要的一個資源,因為程式只有被載入到記憶體中才可以執行;此外,CPU所需要的指令與資料也都是來自記憶體的。可以說,記憶體是影響計算機效能的一個很重要的因素。
分層儲存器體系
在介紹記憶體管理的細節前,先要了解一下分層儲存器體系:
大部分的計算機都有一個儲存器層次結構,即少量的非常快速、昂貴、易變的快取記憶體(cache);若干兆位元組的中等速度、中等價格、易變的主儲存器(RAM);數百兆或數千兆的低速、廉價、不易變的磁碟。這些資源的合理使用與否直接關係著系統的效率。
CPU快取(Cache Memory):是位於CPU與記憶體之間的臨時儲存器,它的容量比記憶體小的多但是交換速度卻比記憶體要快得多。快取的出現主要是為了解決CPU運算速度與記憶體 讀寫速度不匹配的矛盾,因為CPU運算速度要比記憶體讀寫速度快很多,這樣會使CPU花費很長時間等待資料到來或把資料寫入記憶體。
計算機是一種資料處理裝置,它由CPU和記憶體以及外部裝置組成。CPU負責資料處理,記憶體負責儲存,外部裝置負責資料的輸入和輸出,它們之間透過匯流排連線在一起。CPU內部主要由控制器、運算器和暫存器組成。控制器負責指令的讀取和排程,運算器負責指令的運算執行,暫存器負責資料的儲存,它們之間透過CPU內的匯流排連線在一起。每個外部裝置(例如:顯示器、硬碟、鍵盤、滑鼠、網絡卡等等)則是由外設控制器、I/O埠、和輸入輸出硬體組成。外設控制器負責裝置的控制和操作,I/O埠負責資料的臨時儲存,輸入輸出硬體則負責具體的輸入輸出,它們間也透過外部裝置內的匯流排連線在一起。
上面計算機系統結構圖中我們可以看出硬體系統的這種元件化的設計思路總是貫徹到各個環節。
在這套設計思想(馮。諾依曼體系架構)裡面: 總是有一部分負責控制、一部分負責執行、一部分則負責儲存,它之間進行互動以及介面通訊則總是透過匯流排來完成。這種設計思路一樣的可以應用在我們的軟體設計體系裡面:元件和元件之間通訊透過事件的方式來進行解耦處理,而一個元件內部同樣也需要明確好各個部分的職責(一部分負責排程控制、一部分負責執行實現、一部分負責資料儲存)。
計算儲存的層次結構
當前技術沒有能夠提供這樣的儲存器,因此大部分的計算機都有一個儲存器層次結構:
快取記憶體(cache): 少量的非常快速、昂貴、易變的快取記憶體(cache);
主儲存器(RAM): 若干兆位元組的中等速度、中等價格、易變的主儲存器(RAM);
磁碟: 數百兆或數千兆的低速、廉價、不易變的磁碟。
這些資源的合理使用與否直接關係著系統的效率。
二、記憶體使用演化
1、沒有記憶體抽象的年代
在早些的作業系統中,並沒有引入記憶體抽象的概念。程式直接訪問和操作的都是物理記憶體,記憶體的管理也非常簡單,除去作業系統所用的記憶體之外,全部給使用者程式使用,想怎麼折騰都行,只要別超出最大的容量。比如當執行如下指令時:mov reg1,1000
1、無記憶體抽象存在的問題:
這條指令會毫無想象力的將物理地址1000中的內容賦值給暫存器。不難想象,這種記憶體操作方式使得作業系統中存在多程序變得完全不可能,比如MS-DOS,你必須執行完一條指令後才能接著執行下一條。如果是多程序的話,由於直接操作物理記憶體地址,當一個程序給記憶體地址1000賦值後,另一個程序也同樣給記憶體地址賦值,那麼第二個程序對記憶體的賦值會覆蓋第一個程序所賦的值,這回造成兩條程序同時崩潰。
帶來兩個問題:
使用者程式可以訪問任意記憶體,容易破壞作業系統,造成崩潰
同時執行多個程式特別困難
隨著計算機技術發展,要求作業系統支援多程序的需求,所謂多程序,並不需要同時執行這些程序,只要它們都處於 ready 狀態,作業系統快速地在它們之間切換,就能達到同時執行的假象。每個程序都需要記憶體,Context Switch 時,之前記憶體裡的內容怎麼辦?簡單粗暴的方式就是先 dump 到磁碟上,然後再從磁碟上 restore 之前 dump 的內容(如果有的話),但效果並不好,太慢了!
2、記憶體抽象:地址空間
那怎麼才能不慢呢?把程序對應的記憶體依舊留在物理記憶體中,需要的時候就切換到特定的區域。這就涉及到了記憶體的保護機制,畢竟程序之間可以隨意讀取、寫入內容就亂套了,非常不安全。因此作業系統需要對物理記憶體做一層抽象,也就是「地址空間」(Address Space),一個程序的地址空間包含了該程序所有相關記憶體,比如 code / stack / heap。一個 16 KB 的地址空間可能長這樣:
當程式執行時,heap 和 stack 共用中間 free 的區域,當然這只是 OS 層面的抽象。比如下面這段程式碼:
int
x
;
x
=
x
+
3
;
// this is the line of code we are interested in
變成彙編指令後,大概是這樣:
128
:
movl
0x0
(
%
ebx
),
%
eax
;
load
0
+
ebx
into
eax
132
:
addl
$
0x03
,
%
eax
;
add
3
to
eax
register
135
:
movl
%
eax
,
0x0
(
%
ebx
)
;
store
eax
back
to
mem
最前面的是 PC (Program Counter),用來表示當前 code 的索引,比如 CPU 執行到 128 時,進行了 Context Switch(上下文切換),那麼在 Switch 回來後,還可以接著從 132 開始執行(當然需要先把 PC 存起來)。之後的就是彙編程式碼,告訴 CPU 該如何操作。
從程序的角度看,記憶體可能是這樣的:
真實的物理記憶體可能是這樣的:
基址暫存器與界限暫存器可以簡單的動態重定位:每個記憶體地址送到記憶體之前,都會自動加上基址暫存器的內容。
從 32KB 處作為開始,48KB 作為結束。那 32 / 48 可不可以動態設定呢,只要在 CPU 上整兩個暫存器,基址暫存器base 和 界限暫存器bounds 就可以了,base 指明從哪裡開始,bounds 指定哪裡是邊界。 因此真實物理地址和虛擬地址之間的關係是:
physical
address
=
virtual
address
+
base
有時,CPU 上用來做記憶體地址翻譯的也會被叫做「記憶體管理單元 MMU」(Memory Management Unit),隨著功能越來越強大,MMU 也會變得越來越複雜。
base and bounds 這種做法最大的問題在於空間浪費,Stack 和 Heap 中間有一塊 free space,即使沒有用,也被佔著,那如何才能解放這塊區域呢,進入虛擬記憶體。
3、虛擬記憶體
虛擬記憶體是現代作業系統普遍使用的一種技術。前面所講的抽象滿足了多程序的要求,但很多情況下,現有記憶體無法滿足僅僅一個大程序的記憶體要求。物理記憶體不夠用的情況下,如何解決呢?
覆蓋overlays:
在早期的作業系統曾使用覆蓋技術來解決這個問題,將一個程式分為多個塊,基本思想是先將塊0加入記憶體,塊0執行完後,將塊1加入記憶體。依次往復,這個解決方案最大的問題是需要程式設計師去程式進行分塊,這是一個費時費力讓人痛苦不堪的過程。後來這個解決方案的修正版就是虛擬記憶體。
交換swapping:
可以將暫時不能執行的程式(程序)送到外存中,從而獲得空閒記憶體空間來裝入新程式(程序),或讀人儲存在外存中而處於就緒狀態的程式。
虛擬記憶體
:虛擬記憶體的基本思想是,每個程序有用獨立的邏輯地址空間,記憶體被分為大小相等的多個塊,稱為頁(Page)。每個頁都是一段連續的地址。對於程序來看,邏輯上貌似有很多記憶體空間,其中一部分對應物理記憶體上的一塊(稱為頁框,通常頁和頁框大小相等),還有一些沒載入在記憶體中的對應在硬碟上。
三。 物理記憶體:連續分配儲存管理方式
連續分配是指為一個使用者程式分配連續的記憶體空間。連續分配有單一連續儲存管理和分割槽式儲管理兩種方式。
1。 單一連續儲存管理
在這種管理方式中,記憶體被分為兩個區域:系統區和使用者區。應用程式裝入到使用者區,可使用使用者區全部空間。其特點是,最簡單,適用於單使用者、單任務的作業系統。CP/M和 DOS 2.0以下就是採用此種方式。這種方式的最大優點就是易於管理。但也存在著一些問題和不足之處,例如對要求記憶體空間少的程式,造成記憶體浪費;程式全部裝入,使得很少使用的程式部分也佔用—定數量的記憶體。
2。 分割槽式儲存管理
為了支援多道程式系統和分時系統,支援多個程式併發執行,引入了分割槽式儲存管理。分割槽式儲存管理是把記憶體分為一些大小相等或不等的分割槽,作業系統佔用其中一個分割槽,其餘的分割槽由應用程式使用,每個應用程式佔用一個或幾個分割槽。分割槽式儲存管理雖然可以支援併發,但難以進行記憶體分割槽的共享。
分割槽式儲存管理引人了兩個新的問題:
內碎片和外碎片
。
內碎片是佔用分割槽內未被利用的空間,外碎片是佔用分割槽之間難以利用的空閒分割槽(通常是小空閒分割槽)。
為實現分割槽式儲存管理,作業系統應維護的資料結構為分割槽表或分割槽連結串列。表中各表項一般包括每個分割槽的起始地址、大小及狀態(是否已分配)。
分割槽式儲存管理常採用的一項技術就是
記憶體緊縮(compaction)。
1) 固定分割槽(nxedpartitioning)。
固定式分割槽的特點是把記憶體劃分為若干個固定大小的連續分割槽。分割槽大小可以相等:這種作法只適合於多個相同程式的併發執行(處理多個型別相同的物件)。分割槽大小也可以不等:有多個小分割槽、適量的中等分割槽以及少量的大分割槽。根據程式的大小,分配當前空閒的、適當大小的分割槽。
優點
:易於實現,開銷小。
缺點主要有兩個
:內碎片造成浪費;分割槽總數固定,限制了併發執行的程式數目。
2)動態分割槽(dynamic partitioning)。
動態分割槽的特點是動態建立分割槽:在裝入程式時按其初始要求分配,或在其執行過程中透過系統呼叫進行分配或改變分割槽大小。與固定分割槽相比較其優點是:沒有內碎片。但它卻引入了另一種碎片——外碎片。動態分割槽的分割槽分配就是尋找某個空閒分割槽,其大小需大於或等於程式的要求。若是大於要求,則將該分割槽分割成兩個分割槽,其中一個分割槽為要求的大小並標記為“佔用”,而另一個分割槽為餘下部分並標記為“空閒”。分割槽分配的先後次序通常是從記憶體低端到高階。動態分割槽的分割槽釋放過程中有一個要注意的問題是,將相鄰的空閒分割槽合併成一個大的空閒分割槽。
下面列出了幾種常用的分割槽分配演算法:
最先適配法(nrst-fit):
按分割槽在記憶體的先後次序從頭查詢,找到符合要求的第一個分割槽進行分配。該演算法的分配和釋放的時間效能較好,較大的空閒分割槽可以被保留在記憶體高階。但隨著低端分割槽不斷劃分會產生較多小分割槽,每次分配時查詢時間開銷便會增大。
下次適配法(迴圈首次適應演算法 next fit):
按分割槽在記憶體的先後次序,從上次分配的分割槽起查詢(到最後{區時再從頭開始},找到符合要求的第一個分割槽進行分配。該演算法的分配和釋放的時間效能較好,使空閒分割槽分佈得更均勻,但較大空閒分割槽不易保留。
最佳適配法(best-fit):
按分割槽在記憶體的先後次序從頭查詢,找到其大小與要求相差最小的空閒分割槽進行分配。從個別來看,外碎片較小;但從整體來看,會形成較多外碎片優點是較大的空閒分割槽可以被保留。
最壞適配法(worst- fit):
按分割槽在記憶體的先後次序從頭查詢,找到最大的空閒分割槽進行分配。基本不留下小空閒分割槽,不易形成外碎片。但由於較大的空閒分割槽不被保留,當對記憶體需求較大的程序需要執行時,其要求不易被滿足。
3。 夥伴系統
固定分割槽和動態分割槽方式都有不足之處。固定分割槽方式限制了活動程序的數目,當程序大小與空閒分割槽大小不匹配時,記憶體空間利用率很低。動態分割槽方式演算法複雜,回收空閒分割槽時需要進行分割槽合併等,系統開銷較大。夥伴系統方式是對以上兩種記憶體方式的一種折衷方案。
夥伴系統規定,無論已分配分割槽或空閒分割槽,其大小均為 2 的 k 次冪,k 為整數, l≤k≤m,其中:
2^1 表示分配的最小分割槽的大小,
2^m 表示分配的最大分割槽的大小,
通常 2^m是整個可分配記憶體的大小。
假設系統的可利用空間容量為2^m個字, 則系統開始執行時, 整個記憶體區是一個大小為2^m的空閒分割槽。在系統執行過中, 由於不斷的劃分,可能會形成若干個不連續的空閒分割槽,將這些空閒分割槽根據分割槽的大小進行分類,對於每一類具有相同大小的所有空閒分割槽,單獨設立一個空閒分割槽雙向連結串列。這樣,不同大小的空閒分割槽形成了k(0≤k≤m)個空閒分割槽連結串列。
分配步驟:
當需要為程序分配一個長度為n 的儲存空間時:
首先計算一個i 值,使 2^(i-1) 然後在空閒分割槽大小為2^i的空閒分割槽連結串列中查詢。 若找到,即把該空閒分割槽分配給程序。 否則,表明長度為2^i的空閒分割槽已經耗盡,則在分割槽大小為2^(i+1)的空閒分割槽連結串列中尋找。 若存在 2^(i+1)的一個空閒分割槽,則把該空閒分割槽分為相等的兩個分割槽, 這兩個分割槽稱為一對夥伴 ,其中的一個分割槽用於配, 而把另一個加入分割槽大小為2^i的空閒分割槽連結串列中。 若大小為2^(i+1)的空閒分割槽也不存在,則需要查詢大小為2^(i+2)的空閒分割槽, 若找到則對其進行兩次分割: 第一次,將其分割為大小為 2^(i+1)的兩個分割槽,一個用於分配,一個加入到大小為 2^(i+1)的空閒分割槽連結串列中; 第二次,將第一次用於分配的空閒區分割為 2^i的兩個分割槽,一個用於分配,一個加入到大小為 2^i的空閒分割槽連結串列中。 若仍然找不到,則繼續查詢大小為 2^(i+3)的空閒分割槽,以此類推。 由此可見,在最壞的情況下,可能需要對 2^k的空閒分割槽進行 k 次分割才能得到所需分割槽。 與一次分配可能要進行多次分割一樣,一次回收也可能要進行多次合併,如回收大小為2^i的空閒分割槽時,若事先已存在2^i的空閒分割槽時,則應將其與夥伴分割槽合併為大小為2^i+1的空閒分割槽,若事先已存在2^i+1的空閒分割槽時,又應繼續與其夥伴分割槽合併為大小為2^i+2的空閒分割槽,依此類推。 在夥伴系統中,其分配和回收的時間效能取決於查詢空閒分割槽的位置和分割、合併空閒分割槽所花費的時間。與前面所述的多種方法相比較,由於該演算法在回收空閒分割槽時,需要對空閒分割槽進行合併,所以其時間效能比前面所述的分類搜尋演算法差,但比順序搜尋演算法好,而其空間效能則遠優於前面所述的分類搜尋法,比順序搜尋法略差。 需要指出的是,在當前的作業系統中,普遍採用的是下面將要講述的基於分頁和分段機制的虛擬記憶體機制,該機制較夥伴演算法更為合理和高效,但在多處理機系統中,夥伴系統仍不失為一種有效的記憶體分配和釋放的方法,得到了大量的應用。 4。 記憶體緊縮(記憶體碎片化處理) 記憶體緊縮: 將各個佔用分割槽向記憶體一端移動,然後將各個空閒分割槽合併成為一個空閒分割槽。 這種技術在提供了某種程度上的靈活性的同時,也存在著一些弊端,例如:對佔用分割槽進行記憶體資料搬移佔用CPU時間;如果對佔用分割槽中的程式進行“浮動”,則其重定位需要硬體支援。 緊縮時機:每個分割槽釋放後,或記憶體分配找不到滿足條件的空閒分割槽時。 堆結構的儲存管理的分配演算法: 在動態儲存過程中,不管哪個時刻,可利用空間都是-一個地址連續的儲存區,在編譯程式中稱之為“堆”,每次分配都是從這個可利用空間中劃出一塊。其實現辦法是:設立一個指標,稱之為堆指標,始終指向堆的最低(或鍛聯)地址。當用戶申請N個單位的儲存塊時,堆指標向高地址(或 低地址)稱動N個儲存單位,而移動之前的堆指標的值就是分配給使用者的佔用塊的初始地址。例如,某個串處理系統中有A、B、C、D這4個串,其串值長度分別為12,6,10和8。 假設堆指標free的初值為零,則分配給這4個串值的儲存空間的初始地址分別為0。12。18和 28,如圖8。12(a)和(b)所示,分配後的堆指標的值為36。 因此,這種堆結構的儲存管理的分配演算法非常簡單, 釋放記憶體空間執行記憶體緊縮: 回收使用者釋放的空閒塊就比較麻煩。由於系統的可利用空間始終是一個絕址連續的儲存塊,因此回收時必須將所釋放的空間塊合併到整個堆上去才 能重新使用,這就是“儲存策縮”的任務。通常,有兩種做法: 一種是一旦有使用者釋放儲存塊即進行回收緊縮,例始,圖8。12 (a)的堆,在c串釋放儲存塊時即回收緊縮,例如圖8。12 (c)的堆,同時修改串的儲存映像成圖8。12(d)的狀態; 另一種是在程式執行過程中不回收使用者隨時釋放的儲存塊,直到可利用空同不夠分配或堆指標指向最高地址時才進行儲存緊縮。此時緊縮的目的是將堆中所有的空間塊連成一塊,即將所有的佔用塊部集中到 可利用空間的低地地區,而剩餘的高地址區成為一整個地繼連續的空閒塊,如圖8。13所示,其中(a)為緊縮前的狀態,(b)為緊縮後的狀態• 和無用單元收集類似,為實現儲存紫編,首先要對佔用塊進行“標誌”,標誌演算法和無用單元收集類同(儲存塊的結構可能不同),其次需進行下列4步雄作: (1)計算佔用塊的新地址。從最低地址開始巡査整個儲存空間,對每一個佔用塊找到它在緊縮後的新地址。 為此,需設立兩個指標隨巡查向前移動,這兩個指標分別指示佔用 塊在緊縮之前和之後的原地址和新地址。因此,在每個佔用塊的第-·個儲存單位中,除了 設立長度域(儲存該佔用換的大小)和標誌域(儲存區別該儲存塊是佔用塊或空閒塊的標 志)之外,還需設立一個新地址城,以儲存佔用塊在緊縮後應有的新地址,即建立一張新, 舊地址的對照表m (2)修改使用者觸初始變量表,以便在儲存緊縮後用戶程式能繼續正常執行*。 (3)檢查每個佔用塊中儲存的資料, 若有指向其他儲存換的指標,則需作相應修改。 (4)將所有佔用塊遷移到新地址走,這實質上是作傳送資料的工作。 至此,完成了儲存緊縮的操作,最後,將堆指標賦以新值(即緊縮後的空閒儲存區的最低地址)。 可見,儲存緊縮法比無用單元收集法更為複雜,前者不僅要傳送資料(進行佔用塊遷移),而且還有需要修改所有佔用塊中的指標值。因此,儲存緊縮也是個系統操作,且非不得已就不用。 5。 覆蓋技術 引入覆蓋 (overlay) 技術的目標是在較小的可用記憶體中執行較大的程式。這種技術常用於多道程式系統之中,與分割槽式儲存管理配合使用。 覆蓋技術的原理: 一個程式的幾個程式碼段或資料段,按照時間先後來佔用公共的記憶體空間。將程式必要部分(常用功能)的程式碼和資料常駐記憶體;可選部分(不常用功能)平時存放在外存(覆蓋檔案)中,在需要時才裝入記憶體。不存在呼叫關係的模組不必同時裝入到記憶體,從而可以相互覆蓋。 在任何時候只在記憶體中保留所需的指令和資料;當需要其它指令時,它們會裝入到剛剛不再需要的指令所佔用的記憶體空間; 如在同一時刻,CPU只能執行B,C中某一條。B,C之間就可以做覆蓋。 覆蓋技術的缺點 是程式設計時必須劃分程式模組和確定程式模組之間的覆蓋關係,增加程式設計複雜度;從外存裝入覆蓋檔案,以時間延長換取空間節省。 覆蓋的實現方式有兩種:以函式庫方式實現或作業系統支援。 6. 交換技術 交換 (swapping) 技術在多個程式併發執行時,可以將暫時不能執行的程式(程序)送到外存中,從而獲得空閒記憶體空間來裝入新程式(程序),或讀人儲存在外存中而處於就緒狀態的程式。 交換單位為整個程序的地址空間。 交換技術常用於多道程式系統或小型分時系統中,因為這些系統大多采用分割槽儲存管理方式。與分割槽式儲存管理配合使用又稱作“對換”或“滾進/滾出” (roll-in/roll-out)。 原理: 暫停執行記憶體中的程序,將整個程序的地址空間儲存到外存的交換區中(換出swap out),而將外存中由阻塞變為就緒的程序的地址空間讀入到記憶體中,並將該程序送到就緒佇列(換入swap in)。 交換技術 優點之一是增加併發執行的程式數目,並給使用者提供適當的響應時間;與覆蓋技術相比交換技術另一個顯著的優點是不影響程式結構。交換技術本身也存在著不足,例如:對換人和換出的控制增加處理器開銷;程式整個地址空間都進行對換,沒有考慮執行過程中地址訪問的統計特性。 7。 覆蓋與交換比較 1)與覆蓋技術相比,交換不要求程式設計師給出程式段之間的覆蓋結構。 2)交換主要是在程序與作業之間進行,而覆蓋則主要在同一作業或程序內進行。 另外覆蓋只能覆蓋那些與覆蓋程式段無關的程式段。 四。 物理記憶體非連續:頁式和段式儲存管理 在前面的幾種儲存管理方法中,為程序分配的空間是連續的,使用的地址都是物理地址 。如果允許將一個程序分散到許多不連續的空間,就可以 避免記憶體緊縮,減少碎片 。基於這一思想,透過引入程序的邏輯地址,把程序地址空間與實際儲存空間分離,增加儲存管理的靈活性。地址空間和儲存空間兩個基本概念的定義如下: 地址空間:將源程式經過編譯後得到的目標程式,存在於它所限定的地址範圍內,這個範圍稱為地址空間。地址空間是邏輯地址的集合。 儲存空間:指主存中一系列儲存資訊的物理單元的集合,這些單元的編號稱為物理地址儲存空間是物理地址的集合。 根據分配時所採用的基本單位不同,可將離散分配的管理方式分為以下三種: 頁式儲存管理、段式儲存管理和段頁式儲存管理。其中段頁式儲存管理是前兩種結合的產物。 頁式和段式管理區別 頁式和段式系統有許多相似之處。比如,兩者都採用離散分配方式,且都透過地址對映機構來實現地址變換。但概念上兩者也有很多區別,主要表現在: 1)、需求:是資訊的物理單位,分頁是為了實現離散分配方式,以減少記憶體的碎片,提高記憶體的利用率。或者說,分頁僅僅是由於系統管理的需要,而不是使用者的需要。段是資訊的邏輯單位,它含有一組其意義相對完整的資訊。分段的目的是為了更好地滿足使用者的需要。 一條指令或一個運算元可能會跨越兩個頁的分界處,而不會跨越兩個段的分界處。 2)、大小:頁大小固定且由系統決定,把邏輯地址劃分為頁號和頁內地址兩部分,是由機器硬體實現的。段的長度不固定,且決定於使用者所編寫的程式,通常由編譯系統在對源程式進行編譯時根據資訊的性質來劃分。 3)、邏輯地址表示:頁式系統地址空間是一維的,即單一的線性地址空間,程式設計師只需利用一個識別符號,即可表示一個地址。分段的作業地址空間是二維的,程式設計師在標識一個地址時,既需給出段名,又需給出段內地址。 4)、比頁大,因而段表比頁表短,可以縮短查詢時間,提高訪問速度。 五。 頁式儲存管理 1。 基本原理 將程式的邏輯地址空間劃分為固定大小的頁(page),而物理記憶體劃分為同樣大小的頁框(page frame)。程式載入時,可將任意一頁放人記憶體中任意一個頁框,這些頁框不必連續,從而實現了離散分配。該方法需要CPU的硬體支援,來實現邏輯地址和物理地址之間的對映。在頁式儲存管理方式中地址結構由兩部構成,前一部分是頁號,後一部分為頁內地址w(位移量),如圖4所示: 頁式管理方式的優點是: 1)沒有外碎片,每個內碎片不超過頁大比前面所討論的幾種管理方式的最大進步是, 2)一個程式不必連續存放。 3)便於改變程式佔用空間的大小(主要指隨著程式執行,動態生成的資料增多,所要求的地址空間相應增長)。 缺點 是:要求程式全部裝入記憶體,沒有足夠的記憶體,程式就不能執行。 2. 頁式管理的資料結構 在頁式系統中程序建立時,作業系統為程序中所有的頁分配頁框。當程序撤銷時收回所有分配給它的頁框。在程式的執行期間,如果允許程序動態地申請空間,作業系統還要為程序申請的空間分配物理頁框。作業系統為了完成這些功能,必須記錄系統記憶體中實際的頁框使用情況。作業系統還要在程序切換時,正確地切換兩個不同的程序地址空間到物理記憶體空間的對映。這就要求作業系統要記錄每個程序頁表的相關資訊。為了完成上述的功能,—個頁式系統中,一般要採用如下的資料結構。 程序頁表 :完成邏輯頁號(本程序的地址空間)到物理頁面號(實際記憶體空間,也叫塊號)的對映。 每個程序有一個頁表,描述該程序佔用的物理頁面及邏輯排列順序,如圖: 物理頁面表:整個系統有一個物理頁面表,描述物理記憶體空間的分配使用狀況,其資料結構可採用位示圖和空閒頁連結串列。 對於位示圖法,即如果該頁面已被分配,則對應位元位置1,否置0。 請求表:整個系統有一個請求表,描述系統內各個程序頁表的位置和大小,用於地址轉換也可以結合到各程序的PCB(程序控制塊)裡。如圖: 3。 頁式管理地址變換 在頁式系統中,指令所給出的地址分為兩部分:邏輯頁號和頁內地址。 原理 :CPU中的記憶體管理單元(MMU)按邏輯頁號透過查程序頁表得到物理頁框號,將物理頁框號與頁內地址相加形成物理地址(見圖4-4)。 邏輯頁號,頁內偏移地址->查程序頁表,得物理頁號->物理地址: 上述過程通常由處理器的硬體直接完成,不需要軟體參與。通常,作業系統只需在程序切換時,把程序頁表的首地址裝入處理器特定的暫存器中即可。一般來說,頁表儲存在主存之中。這樣處理器每訪問一個在記憶體中的運算元,就要訪問兩次記憶體: 第一次用來查詢頁表將運算元的 邏輯地址變換為物理地址; 第二次完成真正的讀寫操作。 這樣做時間上耗費嚴重。為縮短查詢時間,可以將頁表從記憶體裝入CPU內部的關聯儲存器(例如,快表) 中,實現按內容查詢。此時的地址變換過程是:在CPU給出有效地址後,由地址變換機構自動將頁號送人快表,並將此頁號與快表中的所有頁號進行比較,而且這 種比較是同時進行的。若其中有與此相匹配的頁號,表示要訪問的頁的頁表項在快表中。於是可直接讀出該頁所對應的物理頁號,這樣就無需訪問記憶體中的頁表。由於關聯儲存器的訪問速度比記憶體的訪問速度快得多。 六。 段式儲存管理 1。 基本原理 在段式儲存管理中,將程式的地址空間劃分為若干個段(segment),這樣每個程序有一個二維的地址空間。在前面所介紹的動態分割槽分配方式中,系統為整個程序分配一個連續的記憶體空間。而在段式儲存管理系統中,則為每個段分配一個連續的分割槽,而程序中的各個段可以不連續地存放在記憶體的不同分割槽中。程式載入時,作業系統為所有段分配其所需記憶體,這些段不必連續,物理記憶體的管理採用動態分割槽的管理方法。 在為某個段分配物理記憶體時, 可以採用首先適配法、下次適配法、最佳適配法等方法。 在回收某個段所佔用的空間時, 要注意將收回的空間與其相鄰的空間合併。 段式儲存管理也需要硬體支援,實現邏輯地址到物理地址的對映。 程式透過分段劃分為多個模組,如程式碼段、資料段、共享段: –可以分別編寫和編譯 –可以針對不同型別的段採取不同的保護 –可以按段為單位來進行共享,包括透過動態連結進行程式碼共享 這樣做的優點是:可以分別編寫和編譯源程式的一個檔案,並且可以針對不同型別的段採取不同的保護,也可以按段為單位來進行共享。 總的來說, 段式儲存管理的優點是 :沒有內碎片,外碎片可以透過記憶體緊縮來消除;便於實現記憶體共享。 缺點與頁式儲存管理的缺點相同 ,程序必須全部裝入記憶體。 2. 段式管理的資料結構 為了實現段式管理,作業系統需要如下的資料結構來實現程序的地址空間到物理記憶體空間的對映,並跟蹤物理記憶體的使用情況,以便在裝入新的段的時候,合理地分配記憶體空間。 ·程序段表:描述組成程序地址空間的各段,可以是指向系統段表中表項的索引。每段有段基址(baseaddress),即段內地址。 在系統中為每個程序建立一張段對映表,如圖: ·系統段表 :系統所有佔用段(已經分配的段)。 ·空閒段表 :記憶體中所有空閒段,可以結合到系統段表中。 3。 段式管理的地址變換 在段式 管理系統中,整個程序的地址空間是二維的,即其邏輯地址由段號和段內地址兩部分組成。為了完成程序邏輯地址到物理地址的對映,處理器會查詢記憶體中的段表,由段號得到段的首地址,加上段內地址,得到實際的物理地址。這個過程也是由處理器的硬體直接完成的,作業系統只需在程序切換時,將程序段表的首地址裝入處理器的特定暫存器當中。這個暫存器一般被稱作段表地址暫存器。 更多Linux核心原始碼高階知識請加開發交流Q群篇【318652197】獲取,進群免費獲取相關資料,免費觀看公開課技術分享,入群不虧,快來加入我們吧~ 資源免費領 學習直通車
上一篇:會聲會影怎麼做剪影?