物理內存管理為程序運行提供服務。程序駐留在外存,并使用邏輯地址。
邏輯內存管理的核心工作:邏輯地址空間到物理空間的映射。
邏輯內存管理方式:區式、段式、頁式、段頁式。
一、區式管理法
物理內存采用靜態或動態分區法管理。在加載時,為程序分配一個足夠大的區,其內存在物理上是連續的,起始地址為Base。將程序整個裝入到區中。
采用靜態或動態重定位技術,完成邏輯地址到物理地址的轉換。只需要記錄區的基址和界限。基址用于地址轉換,界限用于越界檢查。
二、段式管理法
1、物理內存采用靜態或動態分區法管理。根據進程對各段的要求,可為其分配多個小內存塊,每塊用于一個段。
2、進程由代碼、數據、堆棧等組成。
每個進程一個段表,段表中的每一項是一個段描述符,描述各區的開始位置、界限、保護信息。
保護信息由訪問方式(只讀、讀寫、執行)、特權級等。
Intel處理器提供6個段寄存器:CS、DS、ES、FS、GS、SS,記錄當前正在使用的段描述符。
Intel 的段描述符
3、
在段式管理中,程序中使用的邏輯地址由段號和偏移量組成。
段號:在進程段表中的序號,用來確定區的開始位置和界線。偏移量:相對于分區開始位置的偏移量,即相對地址,用來定位內存單元。
地址轉換需要硬件支持:由硬件機制動態地完成邏輯地址到物理地址的轉換。
每一次地址轉換之前都要做合法性檢查(硬件完成,不可屏蔽)通過才可進行地址轉換訪問段中內容,越界和不合法訪問不能轉換時產生異常。
4、段式管理可以實現內存共享
若一個段描述符放在多個進程的段表中,這些進程就都可以訪問到它的內容。
5、段式管理的特點、優缺點
一個進程可以占用多個小分區,各小分區之間可以不連續,尺寸可以不一樣(動態分區)。
不存在內部碎片(動態分配);由于分區變小,外部碎片也隨之變少。
可以以小分區為單位換入/換出。需要為每個進程提供一個段表,進程切換時,段表也要隨著切換。
優點:
用戶的邏輯地址空間可大于實際的物理內存空間,可為多道程序運行提供支持。
便于動態連接,從而避免靜態連接造成的某些時間和空間的浪費。
缺點:復雜,增加硬件成本和軟件開銷。段的基地址和大小不規整,隨意。
段式管理的實質是動態分區法。
三、頁式管理法
1、
段式管理只能縮小卻不能消除外部碎片,且段的尺寸不規整。
頁式管理:① 縮小分區的尺寸,使各分區足夠小。② 允許為進程分配多個分區,分區之間可以不連續。
基本思想:
給一個進程分配多個小的分區,屬于一個進程的小分區可以不連續。消除了外部碎片,減少了內部碎片(允許內部碎片)。可以以小分區為單位換入/換出。允許進程部分駐留內存。
2、幀
小分區采用等尺寸分區。將物理內存預先分成多個等尺寸分區,稱為幀(Frame),幀號能完全描述一個幀。
等尺寸分區的內部碎片平均占半個區。大幀管理結構少;內部碎片大,小幀反之。
幀過大 --> 變為靜態分區;幀過小 --> 變為動態分區
為便于管理,幀的尺寸應該是2的指數,研究得到,應在512到8192間。
Intel 處理器的幀尺寸是 4096 字節(4K)。Intel處理器還有4M(1024個頁)、2M 的頁。
3、頁
操作系統自動將進程的邏輯地址空間分割成小塊,大小與幀相同,稱為頁。
以頁為單位為進程分配物理內存。當要加載(換入)進程時,根據進程的頁數為其分配幀,將一個頁加載到一個幀中。
(物理地址空間 --> 幀 ; 邏輯地址空間 --> 頁)
進程在內存中占用的幀可以不連續。物理上不連續,邏輯上連續。
不需要用戶參與,規整,便于虛擬化。
4、頁表
(1)邏輯地址分為兩部分:頁號、偏移量
物理地址分為兩部分:幀號、偏移量
邏輯地址到物理地址的轉換需要知道每個進程頁對應的物理幀,以及每個幀的基地址。
記錄頁與幀對應關系的表稱為頁表。
邏輯地址中的偏移量與物理地址中的偏移量相同,所以將邏輯地址中的頁號換成幀號就得到了物理地址。查表慢,所以地址轉換需要硬件加速。
(2)每個進程都需要一個頁表。
處理器提供一個專用寄存器(PTBR)用于記錄當前進程的頁表基地址。
每次地址轉換都需要多次訪問內存,大大降低了訪存速度,所以通常由處理器提供快速查找緩存TLB(Translation
Look aside Buffer),在其中緩存最近使用的頁表項。
(3)共1M個頁,如果一個表項占用4個字節,則一個頁表需要4MB的內存。
很多進程不會用滿自己的邏輯地址空間,它的頁表的大部分是空的,沒有必要為每個進程都預先建立4MB的頁表。
(4)解決:將頁表分級,變單級頁表為多級頁表。
分級以后,進程的一級頁表必須存在(保存在進程的PCB中)。二級頁表可以不連續,可以不存在,甚至可以被換出/換入。通常情況下,二級頁表是動態創建的,大大減少了頁表占用的內存量。
****? 頁目錄 --> 頁目錄項是頁表在內存的位置 --> 一個進程一個頁表 --> 頁表項是邏輯頁與物理幀的對應關系以及一些控制關系 ****
(5)頁表項中為幀號和保護信息
Intel的頁表項
這是硬件做的。
臟標志:是否被更改過
存取標志:是否被訪問過(不用時可以把部分頁換出,換誰?看最近沒用過的)
用戶/超級用戶標志:特權級
讀/寫標志:讀寫權限
存在標志:這個邏輯頁對應的物理頁是否存在,即是否占內存
5、處理器產生的邏輯地址并不直接送到地址總線上,而要經過內存管理單元(MMU)的處理,MMU負責完成地址的轉換。
CPU把邏輯地址給MMU,MMU把物理地址給內存。
6、管理物理幀和頁的分配和回收 --> 以幀或頁為單位,采用伙伴算法
7、在Intel處理器開機時,頁式管理被關閉,需要顯式將其打開。啟動頁式管理的方法:
① 定義頁目錄/頁表。② 將頁目錄的地址加載到CR3中。③ 將CR0的第31位置1。
打開之后,所有的地址都需要經過頁目錄/頁表轉換(所以地址都是邏輯地址)。
8、(1)何時建立頁表 :(Lazy)程序運行時還未建立頁目錄、頁表,便會產生異常 --> 異常時建
(2)如何定義也目錄、頁表:只要建立起來進程邏輯地址空間與系統物理地址空間的映射關系即可,每個邏輯頁對應一個物理幀。
(3)內核放在1M處,邏輯地址放在3G+1M處,要提前把關系建好(一一對應,差3G)
(4)進程運行過程中要不斷訪問內核,進程的運行離不開內核的支持。
所以將內核嵌在每個進程的邏輯地址空間中,使每個邏輯地址空間都有內核。但在物理地址空間中僅有一個內核,它被所有的邏輯地址空間共享。
為了方便,內核一般放在邏輯地址的高端。在32位處理器中放在 3GB~4GB 之間。內核的邏輯地址的起始地址是0xC0100000(ucore的起始邏輯地址是0xC0000000)
做好的頁目錄、頁表
若超過2G,只有1G在內核有地址,剩余的內核中沒有預先分配地址,為HIGHMEM(高端內存),內核訪問不到,用戶可以。所以內核中不要把1G用滿,留下一塊,用時給他臨時分配一個邏輯地址,用完釋放掉。
eg;邏輯上用戶沒問題,一頁一頁連續的,內核不行,Linux 內核中留了128M,用來臨時分配。
四、段頁式管理法
1、
段式和頁式各有優缺點。Intel處理器采用段頁式內存管理。
段式是必須的,段內內存可以再分頁。
段由段描述符表描述,如GDT,頁由頁目錄、頁表描述。
邏輯地址需先經過段描述符表轉化成線性地址,再經過頁目錄、頁表轉化成物理地址。
示意圖
2、Intel 處理器匯總段式管理不可關閉,但應盡量避免
方法:做四個重疊的大段
ucore 內核定義的 GDT(段描述符表)
分頁機制啟動后,GDTR 指向該 GDT 表。
由于各個段的基址都是0,界限都是最大,所以線性地址與邏輯地址相等,段的作用被屏蔽。起作用的是頁式管理。目前的操作系統中使用的也都是頁式管理。
TSS主要用于切換堆棧。當特權級發生變化時,處理器使用的堆棧也要切換,需要為每個進程至少定義2個堆棧。
3、TSS
TSS是一塊內存空間,當前進程的系統堆棧的棧底保存在TSS中。
需在GDT中為TSS創建描述符,TR指向當前使用的TSS描述符(基址與界限)。
可以為每個進程創建一個TSS,進程切換時改TR;也可以讓所有進程共用一個TSS,TR保持不變,進程切換時改esp0(ss0不變)。
ucore 采用的第二種方法。