哈工大作業系統實驗:地址對映與共享
全域性描述符表GDT和區域性描述符表GDT
一個任務會涉及多個段,每個任務需要一個描述符來描述,為了便於組織管理,80386把描述符組織成線性表。由描述符組成的線性表稱為描述符表。在80386中有三種類型的描述符表:全域性描述符表GDT(Global Descriptor Table)、區域性描述符表LDT(Local Descriptor Table)和中斷描述符表IDT(Interrupt Descriptor Table)。
在整個系統中,全域性描述符表GDT和中斷描述符表IDT只有一張,區域性描述符表可以有若干張,每個任務可以有一張。
每個描述符表本身形成一個特殊的資料段。這樣的特殊資料段最多可包含有8K(8192)個描述符. 每個任務的區域性描述符表LDT含有該任務自己的程式碼段、資料段和堆疊段的描述符,也包含該任務所使用的一些門描述符,如任務門和呼叫門描述符等。隨著任務的切換,系統當前的區域性描述符表LDT也隨之切換。
全域性描述符表GDT含有每一個任務都可能或可以訪問的段的描述符,通常包含描述作業系統所使用的程式碼段、資料段和堆疊段的描述符,也包含多種特殊資料段描述符,如各個用於描述任務LDT的特殊資料段等。
在任務切換時,切換LDT,並不切換GDT
通過LDT可以使各個任務私有的各個段與其它任務相隔離,從而達到受保護的目的。通過GDT可以使各任務都需要使用的段能夠被共享。
一個任務可使用的整個虛擬地址空間分為相等的兩半,一半空間的描述符在全域性描述符表中,另一半空間的描述符在區域性描述符表中。由於全域性和區域性描述符表都可以包含多達8192個描述符,而每個描述符所描述的段的最大值可達4G位元組,因此最大的虛擬地址空間可為: 4GB8192
段選擇子
在真實模式下,邏輯地址空間中儲存單元的地址由段值和段內偏移兩部分組成。 在保護方式下,虛擬地址空間(相當於邏輯地址空間)中儲存單元的地址由段選擇子和段內偏移兩部分組成。 與真實模式相比,段選擇子代替了段值。
段選擇子的高13位是描述符索引(Index)。所謂描述符索引是指描述符在描述符表中的序號
段選擇子的第2位是引用描述符表指示位,標記為TI(Table Indicator),TI=0指示從全域性描述符表GDT中讀取描述符;TI=1指示從區域性描述符表LDT中讀取描述符。
選擇子–>描述符---->段基地址----+偏移->線性地址
選擇子的最低兩位是請求特權級RPL(Requested Privilege Level),用於特權檢查。每當程式試圖訪問一個段時,要把當前特權級與所訪問段的特權級進行比較,以確定是否允許程式對該段的訪問
虛擬地址轉換為線性地址
為了將虛擬地址轉換為線性地址,分段單元執行如下操作。
- 先檢查段選擇子的T1欄位,已決定段描述符號,儲存在全域性段描述符表GDL還是區域性段描述符表中。如果在全域性段描述符表GDL中,則分段單元則從GDTR中得到GDT的線性基地址,相反如果區域性段描述符表中則從LDTR中獲取到LDT的線性基地址。
- 從段選擇子的index索引欄位,計算段描述符的地址,index欄位的值乘以8(一個段描述符的大小是8個位元組),然後這個值(偏移)與GDTR或者LDTR的暫存器的值(全域性/區域性段描述符表的基地址)相加,全域性/區域性段描述符表中偏移為index*8的這個地址就儲存著我們當前段的段描述符。
- 把得到的段描述符的base欄位與邏輯地址額偏移offset值相加就得到了線性地址
分段管理機制結束
接下來是頁式管理
如果沒有采用儲存器分頁管理機制,那麼我們得到的線性地址就直接對應與實體地址,否則,則需要將線性地址轉換為實體地址。
page = frame = block
-
頁 :線性地址被分為以固定長度為單位的組,成為頁。頁內部連續的線性地址空間被對映到連續的實體地址中。
-
頁框:把所有的 RAM 分成固定長度的頁框(page frame)(有時叫做物理頁)。每一個頁框包含一個頁(page),也就是說一個頁框的長度與一個頁的長度一致。頁框是主存的一部分,因此也是一個儲存區域。區分一頁和一個頁框是很重要的,前者只是一個數據塊,可以存放在任何頁框或磁碟中。
-
頁表: 把線性地址對映到實體地址的資料結構稱為頁表(page table)。頁表存放在主存中
32位線性地址被分成三個區域
目錄偏移 | 頁表偏移 | Offset |
---|---|---|
最高10位 | 中間10位 | 最低12位 |
CR3 指向頁目錄指標表(PDPT)的基地址
Directory欄位和Table欄位都是10位長,因此頁目錄和頁表都可以多達1024項。那麼一個頁目錄可以定址到高達 1024 * 1024 * 4096=2^32個儲存單元,這和32位地址所期望的一樣。
哈工大實驗開始
在bochs 中執行這個程式,並且找到i的實體地址然後修改他的值,修改成0讓他跳出死迴圈
#include <stdio.h>
int i = 0x12345678;
int main(void)
{
printf("The logical/virtual address of i is 0x%08x", &i);
fflush(stdout);
while (i)
;
return 0;
}
基本的思想:
- ds段是選擇子 index(描述表內偏移) ti rpl 根據T1是0(GDT)是1(LDT)
- LDTR:是區域性描述符表暫存器 index TI RPL
- GDTR:全域性描述符表暫存器,他的值+LDTR的INDEX *8 就找到 LDT
- 找到LDT 之後 根據組合出base,就是LDT的入口
- base + ds的index *8 就是 段基址+偏移量 在根據上圖得出的線性地址的基址
- &i 就是得出來的偏移
- 基址+偏移就是線性地址 分段結束
得出線性地址0X1000 3004 換算成 二進位制就是 0001000000 0000000011 000000000100 也就是 director = 64 table = 3 offset = 4
- CR+dir*4得到頁目錄
- 頁目錄最高20位 + table*4 得到頁
- 頁最高20位+offset得到實體地址 (這時候檢視該地址的內容,可以看到是I =12345678) 修改為0則完成修改I值,可以跳出迴圈
總結一下過程
- 找段號跟段偏移量(選擇子index就是描述表偏移)
- 找LDT跟GDT
- 根據GDT的段描述符找到LDT入口(GDT+LDTR*8)再後檢視內容,根據描述表結構組合出LDT的地址
- 根據LDT地址檢視內容,組合出線性地址的基址(段基址)
- 段基址+偏移量(ip內容 (通過&得出來))得出線性地址
- 線性地址換算成二進位制分別對應DIR TABLE OFFSET
- CR3+DIR(十進位制)*4得出頁目錄地址,檢視內容最高20位是有效位
- 頁目錄有效位+TABLE(十進位制)*4得出頁表地址,檢視內容,最高20位是有效位
- 頁表 + OFFSET 得出實際實體地址