微處理器對存儲器管理

〇、思維導圖

在這裏插入圖片描述

一、內存管理概述

1. 物理地址、虛擬地址、邏輯地址

這部分要講清楚要寫挺多的,所以我單獨寫了這篇文章:我理解的物理地址、虛擬地址、邏輯地址

2. 實方式與保護方式

(1)實方式

  • 從最早的8086開始說吧,8086有20條地址線,可以在1MB物理地址空間尋址。但是8086的所有寄存器都是16位的,顯然,20位的地址需要兩個16位寄存器一起表示,一個寄存器表示20位中的高4位,另一個寄存器表示20位中的低16位,將二者線性相加即可得到物理地址了。我們可以把高4位看作一個起始地址,低16位看作相對這個起始地址的偏移量。可以發現,高4位地址固定時,低16位描述了一個地址範圍,因此我們不妨更進一步把這看作一個地址段,高4位地址代表段起始地址,低16位代表段中的偏移地址,這就是實方式下所謂的段式內存管理了。高4位地址稱爲段值,放在段寄存器中,低16位地址稱爲偏移,可以看出,一個段長度最大爲216=64KB2^{16}=64KB,最小爲220/216=16B2^{20}/2^{16}=16B(安排了2162^{16}個段)。
  • 8086之後所有的IA32處理器(286/386/pentium/core…),爲了兼容考慮都保留了實方式,實方式下的關於地址的一切都和8086相同
  • 我個人認爲,8086時代的段式內存管理的意義僅在於提供一個方便的用16位寄存器表示20位物理地址的方法,如果8086裝了20位的寄存器,應該就不會有這種分段方式存在了。
  • 由於程序可以任意地修改段寄存器的值,又可以任意提供低16位偏移量,所以任意程序都可以訪問全部1MB物理地址。所以當時的使用的方式系統中同時運行的只有一個應用程序和一個DOS操作系統,操作系統和應用規定了各自能使用的內存地址範圍,比如說DOS只使用高64KB的內存,其它的內存給應用程序使用。如果同時運行兩個程序,內存很可能相互衝突;程序也可能錯誤地改寫了操作系統數據,導致整個系統崩掉

(2)保護方式

  • 80286設計的時候,考慮的一個重點就是如何解決多個程序同時運行時內存衝突的問題。這也是 “保護” 二字的源頭,保護方式下每個進程的內存都不能被其他進程訪問。有了保護方式後,以前8086那種方式才被對應稱爲實方式
  • 要實現進程內存的保護,我們可以把每個進程限制到一個或幾個段中,它只能訪問這些段中的內存空間,而且這些段的分配應該由操作系統決定。
  • 爲了達成這一點,每一個段除了起始地址外需要更多信息了,比如段長度、訪問權限之類的,我們把這些段信息打包在一起,稱它爲段描述符,所有段的段描述符放在一起,存在“段描述符表中”(事實上有全局描述符表GDT、局部描述符表LDT、中斷描述符表IDT等多種表)。顯然段描述符的長度比16長了,還用以前的16位段寄存器存不下這麼多信息,所以我們改在段寄存器中存一個索引,用它指向目標段的段描述符。當一個應用程序內存不夠用時,需要調用一些系統調用,系統就分配一段內存,把將這段內存的信息做成一個描述符加入到GDT或LDT中。
  • 以下是80286的段描述符表
    在這裏插入圖片描述
    可見段基址有24位(286有24根地址線,偏移地址也有24位了),對應到16MB的物理地址空間,段限16位,段長度64KB內可變。
  • 值得一提的是,因爲段選擇子的引入,段寄存器不再直接存儲物理地址,物理地址不再直接計算,而是經過若干轉換才產生,這就留出了靈活操作空間,80286成爲第一款支持虛擬地址的處理器
  • 80286之後的cpu的段式內存管理也繼承了80286的方法,只是地址線變多了,段界限變大了之類,本質上沒什麼區別
  • 我認爲從80286開始的段式內存管理開始具有意義了,各段相互隔離,互不影響,從而多個程序可以在同一個處理器運行而不相互干擾
  • 80386開始,段大小最大可以達到4GB了,爲了細化管理,提高內存的利用率,又引入了分頁管理,其原理和分段差不多,本質也是查表,它是建立在分段基礎上的,把一個大段再劃分成更小的頁,後面再詳細說明。

3. 段式內存管理和頁式內存管理

  1. 簡介

    1. Intel對存儲器的管理分爲段式管理頁式管理

    2. 兩種管理方式的目的:

      1. 段式管理的目的在於:使各段(如代碼段、數據段、堆棧段)相互隔離,互不影響,從而多個程序可以在同一個處理器運行而不相互干擾
      2. 頁式管理的目的在於:實現離散分配方式,以消減內存的外零頭,提高內存的利用率。
    3. 對於一個既分段又分頁的情況,邏輯(虛擬)地址經過分段轉換爲線性地址,再經過分頁轉換爲物理地址。

      1. 線性地址虛擬地址到物理地址變換的中間層,段基址加上偏移地址就成了一個線性地址
      2. 如果同時啓用了分段和分頁,則虛擬地址(邏輯地址形式)經過分段成爲線性地址,再經過分頁成爲物理地址;如果僅啓用了分段機制,那麼線性地址就是物理地址;如果僅啓用了分頁機制,那麼虛擬地址就是線性地址
        在這裏插入圖片描述
    4. 對於段式內存管理的進一步說明:

      • 邏輯段是對程序邏輯意義上的一種劃分,一組完整邏輯意義的程序被劃分成一段,所以邏輯段的長度是不確定的(但最大長度受到段界限制)。邏輯段之間可以相連,也可以不相連甚至重疊
      • 利用這樣的分段,可以實現代碼和數據的隔離,也有利於實現程序的重定位
      • 爲了簡化對存儲器的管理,也可以把代碼、數據、堆棧安排在同一個邏輯段,佔用同一個存儲段的不同區域 (下面的平坦模式就是這種)
    5. 轉載一段分段和分頁的區別:

      分段和分頁其實都是一種對地址的劃分或者映射的方式。兩者的區別主要有以下幾點:
      (1)頁是信息的物理單位,分頁是爲實現離散分配方式,以消減內存的外零頭,提高內存的利用率;或者說,分頁僅僅是由於系統管理的需要,而不是用戶的需要(也是對用戶透明的)。段是信息的邏輯單位,它含有一組其意義相對完整的信息(比如數據段、代碼段和堆棧段等)。分段的目的是爲了能更好的滿足用戶的需要(用戶也是可以使用的)。
      (2)頁的大小固定且由系統確定,把邏輯地址劃分爲頁號和頁內地址兩部分,是由機器硬件實現的,因而一個系統只能有一種大小的頁面。段的長度卻不固定,決定於用戶所編寫的程序,通常由編輯程序在對源程序進行編輯時,根據信息的性質來劃分。
      (3)分頁的作業地址空間是一維的,即單一的線性空間,程序員只須利用一個記憶符(線性地址的16進製表示),即可表示一地址。分段的作業地址空間是二維的,程序員在標識一個地址時,既需給出段名(比如數據段、代碼段和堆棧段等),又需給出段內地址。
      (4)頁和段都有存儲保護機制。但存取權限不同:段有讀、寫和執行三種權限;而頁只有讀和寫兩種權限。

  2. 段式管理的幾種方式(保護方式下)

    1. 基本的平面模式不分段,操作系統和程序可以連續訪問沒有進行分段的地址空間。所有段描述符描述的段基址都是0,所以偏移地址就是線性地址。代碼、數據、堆棧都存在一個大小爲最大線性地址空間的段中。代碼存在一片連續區域,數據堆棧存在另一片連續的區域。
    2. 帶保護的平面模式除了代碼段,其他不分段。段寄存器(DS/SS/ES/FS/GS)都爲0,對於數據段的尋址,偏移地址就是線性地址。類似基本的平面模式,只是如果訪問不存在的(沒有使用的)存儲空間,將產生一般保護異常。這種模式下,代碼段和其他段是分開的,段界可編程
      3
    3. 多段模式分段,每個段都有自己獨立的段描述符,其描述的各自段的起始地址是浮動的(初始編程實現),不限於0,段界可編程。所有保護機制均起作用。若把代碼段以外的段基地址設爲0,則退化爲帶保護的平面模式。
      在這裏插入圖片描述
    4. IA-32E模式:在兼容模式下,段的功能與32位保護方式是一樣的;在64位模式下,段通常是被禁止的,而是產生平面的64位線性地址空間。處理器將CS,DS,ES,SS作爲0處理(FS和GS除外),此時線性地址就是有效地址。
  3. 注意:

    1. 分頁可以在上述任何段式管理模式下進行,處理器的分頁機制將線性地址轉換頁的物理地址。分頁機制提供幾種級別的保護特性,可以被使用或替代段的保護。分頁機制還提供兩級用戶、超級用戶的保護。
    2. 平面模式下,無論是基本還是保護,都禁止分段(依然是段式管理,只是處於同一段)。數據段的尋址,因爲段基址爲0,所以偏移地址(有效地址)就是線性地址,直接進行可能的分頁轉換即可得物理地址。通常情況下Core X系列常用的管理模式是平面模式。

二、實方式下的存儲器管理

任何處理器只要工作在實方式下,其最大尋址空間就是1MB,物理地址長20位,尋址方式同8086,所有地址部件等同於8086的地址加法器,所有處理器尋址的寄存器只有低16位有效(高位全0)

(1)實地址方式下的段式管理機制

  1. 在實地址方式下,只採用段式的存儲管理機制。在1MB大小的存儲空間中,可以開闢若干個段(如代碼段、堆棧段、數據段、擴展數據段等)。段長度爲16B~64KB

  2. 段地址(段值)特指在實地址方式下存放在段寄存器中的內容。它決定了20位物理地址的起始位置,描述了起始地址的高16位,段起始位置的物理地址=段地址*16,一定是16的倍數。

  3. 偏移地址(有效地址)數據或代碼在一個段內的段內偏移量稱爲偏移地址,實方式下長16位,它決定了各類數據在段內的具體位置。偏移地址有兩種體現:

    1. 指令中給出的就是偏移地址,它可以是:
      1. 可間接尋址的寄存器(SUB DX, [EBX])
      2. 直接的偏移地址(mov [2400H], ax)
      3. 通過運算得到的總的偏移地址(MOV EBX, [EDI+EAX*4+300H])
    2. 指針寄存器 IP/BP/SP 或變址寄存器 DI/SI 中內容
  4. 在對存儲器進行操作時,內存一般可分成4個邏輯段,分別稱爲代碼段、數據段、堆棧段和附加數據段,段基址分別放在相應的段寄存器CS、DS、SS和ES中。邏輯段可分配在1MB的任何地方,段與段間可重疊或不重疊、可連續排列、斷續排列
    在這裏插入圖片描述

  5. 由於8086時代的段寄存器只有4個,所以CPU同一時刻只能訪問4個段。其實我們也可以開闢更多段,只要改變某段寄存器的內容指向段起始即可訪問。

(2)實地址方式下物理地址的形成

  1. 實地址方式下,決定物理地址的只有段地址偏移地址,注意不同的段地址和偏移地址要配合使用。系統默認的配合如下:
    在這裏插入圖片描述
    彙編編程時,我們也可以用超越前綴指定取值時所用的段寄存器(如 MOV AX, [ES:BX]),這樣就能擺脫上表的限制
  2. 實地址方式下的存儲器尋址
    1. 段地址與偏移地址:段地址爲該段起始地址的高16位;偏移地址爲指示目的地址在本段中相對偏移量
    2. 邏輯地址:邏輯地址=段地址:偏移地址
    3. 物理地址:物理地址=段地址*16+偏移地址(段地址左移4位再加上偏移)
    4. 注意地址來源規則(上表)
      在這裏插入圖片描述
    5. 示例:
      在這裏插入圖片描述

三、保護方式下的存儲器管理

保護方式下存儲器採用分段+分頁的管理機制,採用段描述符的結構來尋找物理地址。

1. 段描述符和段選擇子

(1)段描述符

  1. 段描述符描述了該段的起始物理地址等信息,包括段基址、段界、段的訪問權等屬性。存放在相關描述符表中。長8個字節,格式如下圖所示。在這裏插入圖片描述

  2. 高32位描述

    名稱 位域 意義
    基址(B31~B24) 31:24 指示這個段在物理存儲器中起始位置 32位段基址的高8位
    粒度 (G) 23 指示段大小的度量單位(只對段界限有效,段基地址總是以字節爲單位 G=0,段以字節(B)爲單位,段大小最大爲1MB
    G=1,段以段以頁(4KB)爲單位,段大小最大爲4GB
    據寬度 (D/B) 22 代碼段,D表示指令所示的地址和操作數默認寬度 D=0,偏移地址 & 數據寬度16位
    D=1,偏移地址 & 數據寬度16位
    堆棧段,B指示默認的堆棧指針寬度 B=0,使用16位的 SP
    B=1,使用32位的 ESP
    擴展數據段,B指示默認的上邊界 B=0,上邊界FFFFH(64KB)
    B=1,上邊界FFFFFFFFH(4GB)
    Long Mode (L) 21 指示代碼段是否爲64位(Intel64 處理器,IA32E專屬位 L=0,不是64位代碼段
    L=1,是64位代碼段
    效位 (AVL) 20 系統軟件使用是否有效(通常由操作系統使用,cpu不管它 AVL=0,系統軟件使用無效(如果DPL=11,AVL必爲0
    AVL=1,系統軟件使用有效(如果DPL=00,AVL必爲1
    界(L19~L16) 19:16 描述該段最大界限 20位段界的高4位
    在位 ( P) 15 指示該段是否在物理存儲器中 P=0,不在,該分段在磁盤外存交換區(虛擬地址)
    P=1,在,該分段在內存中
    述符特權級(DPL) 14:13 在特權測試中使用,共4層,其中0級最高 DPL=00,0級特權(操作系統核心程序)
    DPL=01,1級特權
    DPL=10,2級特權
    DPL=11,3級特權(普通用戶程序)
    描述符特徵(S) 12 指示段描述符特徵 S=0,系統描述符(到底是數據段還是代碼段由TYPE位的值來決定
    S=1,數據段/代碼段描述符
    型(Type) 11:9 對於不同段不一樣 見下表
    問特徵(A) 8 段選擇子是否已裝入段寄存器或被測試指令使用過 A=0,該段未訪問過
    A=1,該段訪問過
    基址(B23~B16) 7:0 指示這個段在物理存儲器中起始位置 32位段基址的中間8位

    在這裏插入圖片描述

  3. 低32位描述:

    名稱 位域 意義
    基址(B15~B0) 31:16 指示這個段在物理存儲器中起始位置 32位段基址的低16位
    段界(L15~L0) 15:0 描述該段最大界限 20位段界的低16位
  4. 說明:

    1. 訪問權字節
      1. 訪問權字節:段描述符高32位中的15:8位域,包括P、PDL、S、Type、A
      2. 規定了此段的特權和屬性,如果對此段的訪問違反了訪問權字節規定的屬性,會引起異常中斷
      3. 這是保護模式 “保護“ 二字的體現
    2. 對於IA32E處理器在64位工作模式下,相比其他區別僅在於多加了一個L代碼寬度位。在此模式下,段基址爲0,因此無須用64位的地址描述,8個字節仍然夠用
  5. 段大小、段界、段地址相關計算

    1. 計算機地址是按字節編址的,我們應當把地址理解爲 “指向一個字節數據”,而不是指向內存中的一個 “位置”(是一個段,而不是一個點),如地址0100H,它代表的是0100H~0101H間的這一個字節,所以:
      1. 段界是基地址爲0時該段的最後一個單位段(1Byte / 4KB)地址,用於確定一個段的界限。所以當段只有一個字節時,段大小等於1,段界卻是0(因爲它指示的是0000H~0001H這一個字節)。
      2. 基地址指向段中第一個字節,末地址指向段中最後一個字節,所以當段只有一個字節時,基地址=末地址
    2. 段大小=(段界+1)*段粒度單位,單位B (字節)
    3. 末地址=基地址+段大小-1,單位B (字節)
      在這裏插入圖片描述

(2) 段選擇子

  1. 引入(本段引用自:這裏

    • 回顧一下實地址方式下的尋址,段寄存器給出了各個段的起始地址,再加上指令給出的16位段內偏移量得到物理地址。可見段寄存器的存在目的是爲了給出邏輯地址中的基地址(對於16位系統,16位的偏移也永遠不可能大於64KB,因此段界不用指定,默認爲最大長度64KB)。再看保護方式,現在邏輯地址中的基地址是通過段描述符給出的(包括段界和訪問權等必要信息),如果按實方式下的思路,我們應該需要一個64位的段寄存器存儲段描述符。
    • 但事實上,爲了兼容考慮,段寄存器一直是16位的,爲了解決這個問題,我們把這些長度爲64-bit的段描述符放入一個數組中,而將段寄存器中的值作爲下標索引來間接引用(事實上,是將段寄存器中的高13位的內容作爲索引)這個全局的數組就是GDT。事實上,在GDT中存放的不僅僅是段描述符,還有其它描述符,它們都是64-bit長。GDT是Protected Mode所必須的數據結構,也是唯一的。另外,正像它的名字(Global Descriptor Table)所揭示的,它是全局可見的,對任何一個任務而言都是這樣
    • 除了GDT之外,IA-32還允許程序員構建與GDT類似的數據結構,它們被稱作LDT(Local Descriptor Table,局部描述符表),但與GDT不同的是,LDT在系統中可以存在多個,並且從LDT的名字可以得知,LDT不是全局可見的,它們只對引用它們的任務可見,每個任務最多可以擁有一個LDT。另外,每一個LDT自身作爲一個段存在,它們的段描述符被放在GDT中。
      LDT只是一個可選的數據結構,你完全可以不用它。使用它或許可以帶來一些方便性,但同時也帶來複雜性,如果你想讓你的OS內核保持簡潔性,以及可移植性,則最好不要使用它
    • 寄存器GDTR用來存放GDT的入口地址寄存器LDTR存放LDT的入口地址。關於GDT、LDT、GDTR、LDTR詳見GDT(全居描述符表)和LDT(局部描述符表)
  2. 段選擇子指示段描述符在描述符表中的起始位置的索引及其相關信息。它是16位的,由指令給出並存放在相應的段寄存器中。(段寄存器中內容,在實方式下是段地址,描述物理地址的高16位;在保護方式下是段選擇子,指示段描述符位置
    在這裏插入圖片描述

  3. 各位描述

    名稱 位域 意義
    15:3 共13位形成描述符所在地址的索引,具體指示描述符在描述符表中的偏移量。對於每一個描述符表可指示2132^{13}(8K)個描述符 左移3位(每個描述符佔8字節)後,是段描述符相對於描述符表基址的偏移地址
    述符表指示器(TI) 2 選擇子選擇了哪一個描述符表 TI=0,選擇全局描述符表(GDT)
    TI=1,選擇局部描述符表(LDT)
    求特權級(RPL) 1:0 構成了選擇子的特權級 二進制表示0~3,其中0爲最高級,3最低
  4. 說明

    1. 除了PRL位域,其餘14個位一共可以尋址2142^{14}個不同的段描述符偏移地址,具體說:可以在兩個描述符表尋找段描述符,每個表可找213=8K2^{13}=8K個。這是虛擬地址空間計算的一部分。可以查看:我理解的物理地址、虛擬地址、邏輯地址

2. IA-32處理器地址轉換

(1) 簡介:

  1. 保護方式下的物理地址形成分爲兩個步進行,首先將48位邏輯地址(段選擇子16位+偏移32位)轉換成32位線性地址,再將32位線性地址轉換成32位物理地址。
  2. 分段將邏輯地址轉換成線性地址的過程稱爲分段,由分段部件SU完成。
    分頁將線性地址轉換顧物理地址的過程稱爲分頁,由分頁部件PU完成。
  3. 分頁是32位處理器獨有的(80386開始),根據頁大小不同可有一次轉換和兩次頁轉換完成分頁功能。

(2)從邏輯地址到線性地址的轉換(分段)

  1. 示意圖
    在這裏插入圖片描述

  2. 轉換過程

    1. 開始轉換前:
      1. 段選擇子段寄存器
      2. 偏移指令中[]給出
      3. 描述符表基地址GDTR給出
    2. 從段選擇子中取出索引編號,乘以段描述符長度8(Bytes)得到段描述符相對描述符表起始的偏移;從寄存器GDTR得到段描述符表起始地址,求和得到段描述符地址
    3. 從描述符表中取出段描述符,進一步取出段基地址
    4. 段基地址和指令給出的偏移相加,得到線性地址
  3. 說明

    1. 尋得段描述符後,cpu自動將其存入段描述符緩衝寄存器,從而提高處理器尋址效率
    2. 分段部件除了完成邏輯地址到線性地址的轉換外,還要檢測保護,如果出現違反保護權限的操作則出現異常中斷

(3)從線性地址到物理地址的轉換(分頁)

  1. 說明:

    1. 分頁部件PU接到分段部件送來的線性地址後,通過分頁將其轉換爲物理地址。
    2. 禁止分頁的情況下,線性地址就是物理地址
    3. 不同處理器分段和分頁尺寸
    處理器 保護方式下段長度 保護方式下頁長度
    8086/8088 無保護方式,實地址方式下長16B ~ 64KB -
    80286 0 ~ 64KB -
    80386 ~ 80486 0 ~ 4GB 4KB
    Pentium I ~ Pentium III 0 ~ 4GB 4KB / 4MB
    Pentium 4 ~ CoreX 0 ~ 4GB 4KB / 4MB /2MB
    CoreX(IA32E模式) 0 ~ 4GB 4KB / 2MB /1GB
  2. 32位物理地址下4KB頁的轉換

    1. 示意圖在這裏插入圖片描述

    2. 轉換過程

      1. 開始轉換前:
        1. 已由段式管理計算出線性地址,分成頁目錄索引 / 頁表索引 / 頁內偏移
        2. 頁目錄表基地址CR3寄存器中[]給出
      2. 求頁目錄描述符所在地址:將CR3中的頁目錄表基地址與DIR值的4倍相加求得頁目錄描述符所在地址。
      3. 找出頁表基地址:從頁目錄描述符中找出頁表首地址(有效位高20位,而低12位爲0)。
      4. 合成頁描述符所在地址:將上述頁表基地址與PAGE值的4倍相加得到頁描述符所在地址。
      5. 找出頁面基地址:從得到的頁描述符中找出頁面對應的基地址(有效位高20位,低12位爲0)。
      6. 合成頁物理地址:將得到的頁面基地址與線性地址的低12位的頁內偏移量相加,即可得到所需的32位物理地址。
    3. 注意

      1. 頁目錄項和頁表項結構如下,其31:22的20位是下一項基地址的高20位地址,基地址低12位爲0(指頁表基地址 / 頁基地址)
        在這裏插入圖片描述
      2. 頁目錄項和頁表項各位含義
        在這裏插入圖片描述
  3. 32位物理地址下4MB頁的轉換

    1. 示意圖
      在這裏插入圖片描述
    2. 轉換過程和4KB頁完全類似,不寫了,頁目錄項結構如下
      在這裏插入圖片描述

(4)例題

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章